1 /* Debug - debug stuff 2 ** 3 ** Initial version by Axel Dörfler, axeld@pinc-software.de 4 ** Some code is based on work previously done by Marcus Overhagen 5 ** 6 ** This file may be used under the terms of the OpenBeOS License. 7 */ 8 9 10 #include "Debug.h" 11 #include "BPlusTree.h" 12 #include "Inode.h" 13 14 #include <KernelExport.h> 15 16 #include <time.h> 17 18 #define Print __out 19 20 21 char * 22 get_tupel(uint32 id) 23 { 24 static unsigned char tupel[5]; 25 26 tupel[0] = 0xff & (id >> 24); 27 tupel[1] = 0xff & (id >> 16); 28 tupel[2] = 0xff & (id >> 8); 29 tupel[3] = 0xff & (id); 30 tupel[4] = 0; 31 for (int16 i = 0;i < 4;i++) { 32 if (tupel[i] < ' ' || tupel[i] > 128) 33 tupel[i] = '.'; 34 } 35 36 return (char *)tupel; 37 } 38 39 40 void 41 dump_block_run(const char *prefix, block_run &run) 42 { 43 Print("%s(%ld, %d, %d)\n", prefix, run.allocation_group, run.start, run.length); 44 } 45 46 47 void 48 dump_inode(Inode &inode) 49 { 50 Print("Inode (%p) {\n", &inode); 51 Print("\tfVolume = %p\n", inode.fVolume); 52 Print("\tfBlockNumber = 0x%16Lx\n", inode.fBlockNumber); 53 Print("\tfNode = %p\n", inode.Node()); 54 Print("\tfTree = %p\n", inode.fTree); 55 Print("\tfAttributes = %p\n", inode.fAttributes); 56 Print("\tfOldSize = 0x%16Lx\n", inode.fOldSize); 57 Print("\tfOldLastModified = 0x%16Lx\n", inode.fOldLastModified); 58 Print("}\n"); 59 } 60 61 62 void 63 dump_super_block(disk_super_block *superBlock) 64 { 65 Print("disk_super_block:\n"); 66 Print(" name = %s\n", superBlock->name); 67 Print(" magic1 = %#08lx (%s) %s\n", superBlock->magic1, get_tupel(superBlock->magic1), (superBlock->magic1 == SUPER_BLOCK_MAGIC1 ? "valid" : "INVALID")); 68 Print(" fs_byte_order = %#08lx (%s)\n", superBlock->fs_byte_order, get_tupel(superBlock->fs_byte_order)); 69 Print(" block_size = %lu\n", superBlock->block_size); 70 Print(" block_shift = %lu\n", superBlock->block_shift); 71 Print(" num_blocks = %Lu\n", superBlock->num_blocks); 72 Print(" used_blocks = %Lu\n", superBlock->used_blocks); 73 Print(" inode_size = %lu\n", superBlock->inode_size); 74 Print(" magic2 = %#08lx (%s) %s\n", superBlock->magic2, get_tupel(superBlock->magic2), (superBlock->magic2 == (int)SUPER_BLOCK_MAGIC2 ? "valid" : "INVALID")); 75 Print(" blocks_per_ag = %lu\n", superBlock->blocks_per_ag); 76 Print(" ag_shift = %lu (%ld bytes)\n", superBlock->ag_shift, 1L << superBlock->ag_shift); 77 Print(" num_ags = %lu\n", superBlock->num_ags); 78 Print(" flags = %#08lx (%s)\n", superBlock->flags, get_tupel(superBlock->flags)); 79 dump_block_run(" log_blocks = ", superBlock->log_blocks); 80 Print(" log_start = %Lu\n", superBlock->log_start); 81 Print(" log_end = %Lu\n", superBlock->log_end); 82 Print(" magic3 = %#08lx (%s) %s\n", superBlock->magic3, get_tupel(superBlock->magic3), (superBlock->magic3 == SUPER_BLOCK_MAGIC3 ? "valid" : "INVALID")); 83 dump_block_run(" root_dir = ", superBlock->root_dir); 84 dump_block_run(" indices = ", superBlock->indices); 85 } 86 87 88 void 89 dump_data_stream(data_stream *stream) 90 { 91 Print("data_stream:\n"); 92 for (int i = 0; i < NUM_DIRECT_BLOCKS; i++) { 93 if (!stream->direct[i].IsZero()) { 94 Print(" direct[%02d] = ",i); 95 dump_block_run("",stream->direct[i]); 96 } 97 } 98 Print(" max_direct_range = %Lu\n", stream->max_direct_range); 99 100 if (!stream->indirect.IsZero()) 101 dump_block_run(" indirect = ", stream->indirect); 102 103 Print(" max_indirect_range = %Lu\n", stream->max_indirect_range); 104 105 if (!stream->double_indirect.IsZero()) 106 dump_block_run(" double_indirect = ", stream->double_indirect); 107 108 Print(" max_double_indirect_range = %Lu\n", stream->max_double_indirect_range); 109 Print(" size = %Lu\n", stream->size); 110 } 111 112 113 void 114 dump_inode(bfs_inode *inode) 115 { 116 Print("inode:\n"); 117 Print(" magic1 = %08lx (%s) %s\n", inode->magic1, 118 get_tupel(inode->magic1), (inode->magic1 == INODE_MAGIC1 ? "valid" : "INVALID")); 119 dump_block_run( " inode_num = ", inode->inode_num); 120 Print(" uid = %lu\n", inode->uid); 121 Print(" gid = %lu\n", inode->gid); 122 Print(" mode = %08lx\n", inode->mode); 123 Print(" flags = %08lx\n", inode->flags); 124 Print(" create_time = %Ld (%Ld)\n", inode->create_time, 125 inode->create_time >> INODE_TIME_SHIFT); 126 Print(" last_modified_time = %Ld (%Ld)\n", inode->last_modified_time, 127 inode->last_modified_time >> INODE_TIME_SHIFT); 128 dump_block_run( " parent = ", inode->parent); 129 dump_block_run( " attributes = ", inode->attributes); 130 Print(" type = %lu\n", inode->type); 131 Print(" inode_size = %lu\n", inode->inode_size); 132 Print(" etc = %#08lx\n", inode->etc); 133 Print(" short_symlink = %s\n", 134 S_ISLNK(inode->mode) && (inode->flags & INODE_LONG_SYMLINK) == 0 ? 135 inode->short_symlink : "-"); 136 dump_data_stream(&(inode->data)); 137 Print(" --\n pad[0] = %08lx\n", inode->pad[0]); 138 Print(" pad[1] = %08lx\n", inode->pad[1]); 139 Print(" pad[2] = %08lx\n", inode->pad[2]); 140 Print(" pad[3] = %08lx\n", inode->pad[3]); 141 } 142 143 144 void 145 dump_bplustree_header(bplustree_header *header) 146 { 147 Print("bplustree_header:\n"); 148 Print(" magic = %#08lx (%s) %s\n", header->magic, 149 get_tupel(header->magic), (header->magic == BPLUSTREE_MAGIC ? "valid" : "INVALID")); 150 Print(" node_size = %lu\n", header->node_size); 151 Print(" max_number_of_levels = %lu\n", header->max_number_of_levels); 152 Print(" data_type = %lu\n", header->data_type); 153 Print(" root_node_pointer = %Ld\n", header->root_node_pointer); 154 Print(" free_node_pointer = %Ld\n", header->free_node_pointer); 155 Print(" maximum_size = %Lu\n", header->maximum_size); 156 } 157 158 159 #define DUMPED_BLOCK_SIZE 16 160 161 void 162 dump_block(const char *buffer,int size) 163 { 164 for(int i = 0;i < size;) { 165 int start = i; 166 167 for(;i < start+DUMPED_BLOCK_SIZE;i++) { 168 if (!(i % 4)) 169 Print(" "); 170 171 if (i >= size) 172 Print(" "); 173 else 174 Print("%02x",*(unsigned char *)(buffer+i)); 175 } 176 Print(" "); 177 178 for(i = start;i < start + DUMPED_BLOCK_SIZE;i++) { 179 if (i < size) { 180 char c = *(buffer+i); 181 182 if (c < 30) 183 Print("."); 184 else 185 Print("%c",c); 186 } else 187 break; 188 } 189 Print("\n"); 190 } 191 } 192 193 194 void 195 dump_bplustree_node(bplustree_node *node,bplustree_header *header,Volume *volume) 196 { 197 Print("bplustree_node:\n"); 198 Print(" left_link = %Ld\n", node->left_link); 199 Print(" right_link = %Ld\n", node->right_link); 200 Print(" overflow_link = %Ld\n", node->overflow_link); 201 Print(" all_key_count = %u\n", node->all_key_count); 202 Print(" all_key_length = %u\n", node->all_key_length); 203 204 if (header == NULL) 205 return; 206 207 if (node->all_key_count > node->all_key_length 208 || uint32(node->all_key_count * 10) > (uint32)header->node_size 209 || node->all_key_count == 0) { 210 Print("\n"); 211 dump_block((char *)node, header->node_size/*, sizeof(off_t)*/); 212 return; 213 } 214 215 Print("\n"); 216 for (int32 i = 0;i < node->all_key_count;i++) { 217 uint16 length; 218 char buffer[256], *key = (char *)node->KeyAt(i, &length); 219 if (length > 255 || length == 0) { 220 Print(" %2ld. Invalid length (%u)!!\n", i, length); 221 dump_block((char *)node, header->node_size/*, sizeof(off_t)*/); 222 break; 223 } 224 memcpy(buffer, key, length); 225 buffer[length] = '\0'; 226 227 off_t *value = node->Values() + i; 228 if ((uint32)value < (uint32)node || (uint32)value > (uint32)node + header->node_size) 229 Print(" %2ld. Invalid Offset!!\n", i); 230 else { 231 Print(" %2ld. ", i); 232 if (header->data_type == BPLUSTREE_STRING_TYPE) 233 Print("\"%s\"", buffer); 234 else if (header->data_type == BPLUSTREE_INT32_TYPE) 235 Print("int32 = %ld (0x%lx)", *(int32 *)&buffer, *(int32 *)&buffer); 236 else if (header->data_type == BPLUSTREE_UINT32_TYPE) 237 Print("uint32 = %lu (0x%lx)", *(uint32 *)&buffer, *(uint32 *)&buffer); 238 else if (header->data_type == BPLUSTREE_INT64_TYPE) 239 Print("int64 = %Ld (0x%Lx)", *(int64 *)&buffer, *(int64 *)&buffer); 240 else 241 Print("???"); 242 243 off_t offset = *value & 0x3fffffffffffffffLL; 244 Print(" (%d bytes) -> %Ld", length, offset); 245 if (volume != NULL) { 246 block_run run = volume->ToBlockRun(offset); 247 Print(" (%ld, %d)", run.allocation_group, run.start); 248 } 249 if (bplustree_node::LinkType(*value) == BPLUSTREE_DUPLICATE_FRAGMENT) 250 Print(" (duplicate fragment %Ld)\n", *value & 0x3ff); 251 else if (bplustree_node::LinkType(*value) == BPLUSTREE_DUPLICATE_NODE) 252 Print(" (duplicate node)\n"); 253 else 254 Print("\n"); 255 } 256 } 257 } 258 259 260 // #pragma mark - 261 262 263 #ifndef USER 264 //#warn Don't mount more than once... would register twice the debugger commands! 265 266 static int 267 dbg_inode(int argc, char **argv) 268 { 269 if (argc < 2) { 270 kprintf("usage: obfsinode ptr-to-inode\n"); 271 return 0; 272 } 273 274 Inode *inode = (Inode *)parse_expression(argv[1]); 275 dump_inode(*inode); 276 277 return B_OK; 278 } 279 280 #endif 281 282 void 283 remove_debugger_commands() 284 { 285 #ifndef USER 286 remove_debugger_command("obfsinode", dbg_inode); 287 #endif 288 } 289 290 291 void 292 add_debugger_commands() 293 { 294 #ifndef USER 295 add_debugger_command("obfsinode", dbg_inode, "dump an Inode object"); 296 #endif 297 } 298 299