elfinspect.c (29024B)
1 /* See LICENSE for license details. */ 2 #define local_persist static 3 #define global static 4 #define function static 5 6 /* TODO(rnp) platform specific */ 7 #define ASSERT(c) do { if (!(c)) asm("int3; nop"); } while (0) 8 #define TODO(c) ASSERT(c) 9 10 #define countof(a) (sizeof(a) / sizeof(*a)) 11 12 #define static_assert(c, msg) _Static_assert(c, msg) 13 14 #define KB(a) ((u64)a << 10ULL) 15 #define MB(a) ((u64)a << 20ULL) 16 17 typedef struct {u8 *beg, *end;} Arena; 18 19 #define str8(s) (str8){.len = countof(s) - 1, .data = (u8 *)s} 20 typedef struct { iz len; u8 *data;} str8; 21 22 typedef struct { 23 u8 *data; 24 iz index; 25 iz count; 26 b32 errors; 27 } str8_reader; 28 29 /* NOTE: platform api; defined here so that other platform symbols are not visible to this TU */ 30 function str8 os_map_file(u8 *); 31 32 /* X(name, value, pretty) */ 33 #define ELF_FORMATS \ 34 X(EF_NONE, 0, "Unknown") \ 35 X(EF_32, 1, "ELF32") \ 36 X(EF_64, 2, "ELF64") 37 38 #define ELF_ENDIANNESS \ 39 X(EEK_NONE, 0, "Unknown") \ 40 X(EEK_LITTLE, 1, "Little-Endian") \ 41 X(EEK_BIG, 2, "Big-Endian") 42 43 #define ELF_OS_ABI \ 44 X(ELF_ABI_SYSV, 0x00, "System-V") \ 45 X(ELF_ABI_HPUX, 0x01, "HP-UX") \ 46 X(ELF_ABI_NETBSD, 0x02, "NetBSD") \ 47 X(ELF_ABI_GNU, 0x03, "GNU Hurd") \ 48 X(ELF_ABI_SOLARIS, 0x06, "Solaris") \ 49 X(ELF_ABI_AIX, 0x07, "AIX") \ 50 X(ELF_ABI_IRIX, 0x08, "IRIX") \ 51 X(ELF_ABI_FREEBSD, 0x09, "FreeBSD") \ 52 X(ELF_ABI_TRU64, 0x0a, "Tru64") \ 53 X(ELF_ABI_MODESTO, 0x0b, "Novel Modesto") \ 54 X(ELF_ABI_OPENBSD, 0x0c, "OpenBSD") \ 55 X(ELF_ABI_OPENVMS, 0x0d, "OpenVMS") \ 56 X(ELF_ABI_NONSTOP, 0x0e, "NonStop Kernel") \ 57 X(ELF_ABI_AROS, 0x0f, "AROS") \ 58 X(ELF_ABI_FENIX, 0x10, "Fenix") \ 59 X(ELF_ABI_ARM, 0x61, "ARM") \ 60 X(ELF_ABI_STANDALONE, 0xff, "Free Standing") 61 62 #define ELF_KINDS \ 63 X(ELF_KIND_NONE, 0x0000, "Unknown") \ 64 X(ELF_KIND_REL, 0x0001, "Relocatable") \ 65 X(ELF_KIND_EXEC, 0x0002, "Executable") \ 66 X(ELF_KIND_DYN, 0x0003, "Shared Object") \ 67 X(ELF_KIND_CORE, 0x0004, "Core Dump") 68 69 #define X(name, value, pretty) name = value, 70 typedef enum { ELF_FORMATS } ELFFormat; 71 typedef enum { ELF_ENDIANNESS } ELFEndianKind; 72 typedef enum { ELF_OS_ABI } ELFABIKind; 73 typedef enum { ELF_KINDS } ELFKind; 74 #undef X 75 76 /* X(ctype, name) */ 77 #define ELF_HEADER_MEMBERS \ 78 X(ELFFormat, format) \ 79 X(ELFEndianKind, endianness) \ 80 X(ELFABIKind, abi) \ 81 X(ELFKind, kind) \ 82 X(u16, abi_version) \ 83 X(u16, machine) \ 84 X(u32, version) \ 85 X(u64, entry_point_offset) \ 86 X(u64, program_header_offset) \ 87 X(u64, section_header_offset) \ 88 X(u32, flags) \ 89 X(u16, elf_header_size) \ 90 X(u16, program_header_entry_size) \ 91 X(u16, program_header_count) \ 92 X(u16, section_header_entry_size) \ 93 X(u16, section_header_count) \ 94 X(u16, section_header_name_table_index) 95 96 #define X(ctype, name) ctype name; 97 typedef struct {ELF_HEADER_MEMBERS} ELFHeader; 98 #undef X 99 100 typedef enum { 101 ESK_NULL = 0, 102 ESK_PROGBITS = 1, 103 ESK_SYMBOL_TABLE = 2, 104 ESK_STR_TABLE = 3, 105 ESK_RELA = 4, 106 ESK_HASH = 5, 107 ESK_DYNAMIC = 6, 108 ESK_NOTE = 7, 109 ESK_NOBITS = 8, 110 ESK_REL = 9, 111 ESK_SHLIB = 10, 112 ESK_DYNSYM = 11, 113 ESK_INIT_ARRAY = 14, 114 ESK_FINI_ARRAY = 15, 115 ESK_PREINIT_ARR = 16, 116 ESK_GROUP = 17, 117 ESK_SYMTAB_SHND = 18, 118 ESK_RELR = 19, 119 ESK_NUM = 20, 120 ESK_LOPROC = 0x70000000, 121 ESK_HIPROC = 0x7fffffff, 122 ESK_LOUSER = 0x80000000, 123 ESK_HIUSER = 0x8fffffff, 124 } ELFSectionKind; 125 static_assert(sizeof(ELFSectionKind) == 4, "sizeof(ELFSectionKind) must be 4 bytes"); 126 127 /* X(ctype, name) */ 128 #define ELF_SECTION_HEADER_MEMBERS(ptrsize) \ 129 X(u32, name_table_offset) \ 130 X(ELFSectionKind, kind) \ 131 X(ptrsize, flags) \ 132 X(ptrsize, addr) \ 133 X(ptrsize, offset) \ 134 X(ptrsize, size) \ 135 X(u32, link) \ 136 X(u32, info) \ 137 X(ptrsize, addralign) \ 138 X(ptrsize, entsize) 139 140 #define X(ctype, name) ctype name; 141 typedef struct {ELF_SECTION_HEADER_MEMBERS(u32)} ELFSectionHeader32; 142 typedef struct {ELF_SECTION_HEADER_MEMBERS(u64)} ELFSectionHeader64; 143 #undef X 144 145 typedef struct { 146 str8 name; 147 union { 148 ELFSectionHeader64 sh64; 149 ELFSectionHeader32 sh32; 150 }; 151 } ELFSectionHeader; 152 153 typedef struct { 154 ELFSectionHeader *header; 155 str8 store; 156 } ELFSection; 157 158 typedef enum { 159 DUT_UNKNOWN = 0x00, 160 DUT_COMPILE = 0x01, 161 DUT_TYPE = 0x02, 162 DUT_PARTIAL = 0x03, 163 DUT_SKELETON = 0x04, 164 DUT_SPLIT_COMPILE = 0x05, 165 DUT_SPLIT_TYPE = 0x06, 166 DUT_LO_USER = 0x80, 167 DUT_HI_USER = 0xff 168 } DWARFUnitKind; 169 170 typedef struct { 171 u64 length; 172 u64 abbreviation_offset; 173 DWARFUnitKind kind; 174 u16 version; 175 u8 address_size; 176 u8 dwarf_64; 177 } DWARFUnitHeader; 178 179 typedef enum { 180 DATK_SIBLING = 0x01, 181 DATK_LOCATION = 0x02, 182 DATK_NAME = 0x03, 183 DATK_ORDERING = 0x09, 184 DATK_BYTE_SIZE = 0x0b, 185 DATK_BIT_OFFSET = 0x0c, 186 DATK_BIT_SIZE = 0x0d, 187 DATK_STMT_LIST = 0x10, 188 DATK_LOW_PC = 0x11, 189 DATK_HIGH_PC = 0x12, 190 DATK_LANGUAGE = 0x13, 191 DATK_DISCR = 0x15, 192 DATK_DISCR_VALUE = 0x16, 193 DATK_VISIBILITY = 0x17, 194 DATK_IMPORT = 0x18, 195 DATK_STRING_LENGTH = 0x19, 196 DATK_COMMON_REFERENCE = 0x1a, 197 DATK_COMP_DIR = 0x1b, 198 DATK_CONST_VALUE = 0x1c, 199 DATK_CONTAINING_TYPE = 0x1d, 200 DATK_DEFAULT_VALUE = 0x1e, 201 DATK_INLINE = 0x20, 202 DATK_IS_OPTIONAL = 0x21, 203 DATK_LOWER_BOUND = 0x22, 204 DATK_PRODUCER = 0x25, 205 DATK_PROTOTYPED = 0x27, 206 DATK_RETURN_ADDR = 0x2a, 207 DATK_START_SCOPE = 0x2c, 208 DATK_BIT_STRIDE = 0x2e, 209 DATK_UPPER_BOUND = 0x2f, 210 DATK_ABSTRACT_ORIGIN = 0x31, 211 DATK_ACCESSIBILITY = 0x32, 212 DATK_ADDRESS_CLASS = 0x33, 213 DATK_ARTIFICIAL = 0x34, 214 DATK_BASE_TYPES = 0x35, 215 DATK_CALLING_CONVENTION = 0x36, 216 DATK_COUNT = 0x37, 217 DATK_DATA_MEMBER_LOCATION = 0x38, 218 DATK_DECL_COLUMN = 0x39, 219 DATK_DECL_FILE = 0x3a, 220 DATK_DECL_LINE = 0x3b, 221 DATK_DECLARATION = 0x3c, 222 DATK_DISCR_LIST = 0x3d, 223 DATK_ENCODING = 0x3e, 224 DATK_EXTERNAL = 0x3f, 225 DATK_FRAME_BASE = 0x40, 226 DATK_FRIEND = 0x41, 227 DATK_IDENTIFIER_CASE = 0x42, 228 DATK_MACRO_INFO = 0x43, 229 DATK_NAMELIST_ITEM = 0x44, 230 DATK_PRIORITY = 0x45, 231 DATK_SEGMENT = 0x46, 232 DATK_SPECIFICATION = 0x47, 233 DATK_STATIC_LINK = 0x48, 234 DATK_TYPE = 0x49, 235 DATK_USE_LOCATION = 0x4a, 236 DATK_VARIABLE_PARAMETER = 0x4b, 237 DATK_VIRTUALITY = 0x4c, 238 DATK_VTABLE_ELEM_LOCATION = 0x4d, 239 DATK_ALLOCATED = 0x4e, 240 DATK_ASSOCIATED = 0x4f, 241 DATK_DATA_LOCATION = 0x50, 242 DATK_BYTE_STRIDE = 0x51, 243 DATK_ENTRY_PC = 0x52, 244 DATK_USE_UTF8 = 0x53, 245 DATK_EXTENSION = 0x54, 246 DATK_RANGES = 0x55, 247 DATK_TRAMPOLINE = 0x56, 248 DATK_CALL_COLUMN = 0x57, 249 DATK_CALL_FILE = 0x58, 250 DATK_CALL_LINE = 0x59, 251 DATK_DESCRIPTION = 0x5a, 252 DATK_BINARY_SCALE = 0x5b, 253 DATK_DECIMAL_SCALE = 0x5c, 254 DATK_SMALL = 0x5d, 255 DATK_DECIMAL_SIGN = 0x5e, 256 DATK_DIGIT_COUNT = 0x5f, 257 DATK_PICTURE_STRING = 0x60, 258 DATK_MUTABLE = 0x61, 259 DATK_THREADS_SCALED = 0x62, 260 DATK_EXPLICIT = 0x63, 261 DATK_OBJECT_POINTER = 0x64, 262 DATK_ENDIANITY = 0x65, 263 DATK_ELEMENTAL = 0x66, 264 DATK_PURE = 0x67, 265 DATK_RECURSIVE = 0x68, 266 DATK_SIGNATURE = 0x69, 267 DATK_MAIN_SUBPROGRAM = 0x6a, 268 DATK_DATA_BIT_OFFSET = 0x6b, 269 DATK_CONST_EXPR = 0x6c, 270 DATK_ENUM_CLASS = 0x6d, 271 DATK_LINKAGE_NAME = 0x6e, 272 DATK_STRING_LENGTH_BIT_SIZE = 0x6f, 273 DATK_STRING_LENGTH_BYTE_SIZE = 0x70, 274 DATK_RANK = 0x71, 275 DATK_STR_OFFSETS_BASE = 0x72, 276 DATK_ADDR_BASE = 0x73, 277 DATK_RNGLISTS_BASE = 0x74, 278 DATK_DWO_NAME = 0x76, 279 DATK_REFERENCE = 0x77, 280 DATK_RVALUE_REFERENCE = 0x78, 281 DATK_MACROS = 0x79, 282 DATK_CALL_ALL_CALLS = 0x7a, 283 DATK_CALL_ALL_SOURCE_CALLS = 0x7b, 284 DATK_CALL_ALL_TAIL_CALLS = 0x7c, 285 DATK_CALL_RETURN_PC = 0x7d, 286 DATK_CALL_VALUE = 0x7e, 287 DATK_CALL_ORIGIN = 0x7f, 288 DATK_CALL_PARAMETER = 0x80, 289 DATK_CALL_PC = 0x81, 290 DATK_CALL_TAIL_CALL = 0x82, 291 DATK_CALL_TARGET = 0x83, 292 DATK_CALL_TARGET_CLOBBERED = 0x84, 293 DATK_CALL_DATA_LOCATION = 0x85, 294 DATK_CALL_DATA_VALUE = 0x86, 295 DATK_NORETURN = 0x87, 296 DATK_ALIGNMENT = 0x88, 297 DATK_EXPORT_SYMBOLS = 0x89, 298 DATK_DELETED = 0x8a, 299 DATK_DEFAULTED = 0x8b, 300 DATK_LOCLISTS_BASE = 0x8c, 301 DATK_LO_USER = 0x2000, 302 DATK_HI_USER = 0x3fff, 303 } DWARFAttributeKind; 304 305 typedef enum { 306 DFK_ADDR = 0x01, 307 DFK_BLOCK2 = 0x03, 308 DFK_BLOCK4 = 0x04, 309 DFK_DATA2 = 0x05, 310 DFK_DATA4 = 0x06, 311 DFK_DATA8 = 0x07, 312 DFK_STRING = 0x08, 313 DFK_BLOCK = 0x09, 314 DFK_BLOCK1 = 0x0a, 315 DFK_DATA1 = 0x0b, 316 DFK_FLAG = 0x0c, 317 DFK_SDATA = 0x0d, 318 DFK_STRP = 0x0e, 319 DFK_UDATA = 0x0f, 320 DFK_REF_ADDR = 0x10, 321 DFK_REF1 = 0x11, 322 DFK_REF2 = 0x12, 323 DFK_REF4 = 0x13, 324 DFK_REF8 = 0x14, 325 DFK_REF_UDATA = 0x15, 326 DFK_INDIRECT = 0x16, 327 DFK_SEC_OFFSET = 0x17, 328 DFK_EXPRLOC = 0x18, 329 DFK_FLAG_PRESENT = 0x19, 330 DFK_STRX = 0x1a, 331 DFK_ADDRX = 0x1b, 332 DFK_REF_SUP4 = 0x1c, 333 DFK_STRP_SUP = 0x1d, 334 DFK_DATA16 = 0x1e, 335 DFK_LINE_STRP = 0x1f, 336 DFK_REF_SIG8 = 0x20, 337 DFK_IMPLICIT_CONST = 0x21, 338 DFK_LOCLISTX = 0x22, 339 DFK_RNGLISTX = 0x23, 340 DFK_REF_SUP8 = 0x24, 341 DFK_STRX1 = 0x25, 342 DFK_STRX2 = 0x26, 343 DFK_STRX3 = 0x27, 344 DFK_STRX4 = 0x28, 345 DFK_ADDRX1 = 0x29, 346 DFK_ADDRX2 = 0x2a, 347 DFK_ADDRX3 = 0x2b, 348 DFK_ADDRX4 = 0x2c, 349 } DWARFFormKind; 350 351 typedef struct { 352 DWARFAttributeKind kind; 353 DWARFFormKind form_kind; 354 } DWARFAttribute; 355 356 typedef enum { 357 DAK_ARRAY_TYPE = 0x01, 358 DAK_CLASS_TYPE = 0x02, 359 DAK_ENTRY_POINT = 0x03, 360 DAK_ENUMERATION_TYPE = 0x04, 361 DAK_FORMAL_PARAMETER = 0x05, 362 DAK_IMPORTED_DECLARATION = 0x08, 363 DAK_LABEL = 0x0a, 364 DAK_LEXICAL_BLOCK = 0x0b, 365 DAK_MEMBER = 0x0d, 366 DAK_POINTER_TYPE = 0x0f, 367 DAK_REFERENCE_TYPE = 0x10, 368 DAK_COMPILE_UNIT = 0x11, 369 DAK_STRING_TYPE = 0x12, 370 DAK_STRUCTURE_TYPE = 0x13, 371 DAK_SUBROUTINE_TYPE = 0x15, 372 DAK_TYPEDEF = 0x16, 373 DAK_UNION_TYPE = 0x17, 374 DAK_UNSPECIFIED_PARAMETERS = 0x18, 375 DAK_VARIANT = 0x19, 376 DAK_COMMON_BLOCK = 0x1a, 377 DAK_COMMON_INCLUSION = 0x1b, 378 DAK_INHERITANCE = 0x1c, 379 DAK_INLINED_SUBROUTINE = 0x1d, 380 DAK_MODULE = 0x1e, 381 DAK_PTR_TO_MEMBER_TYPE = 0x1f, 382 DAK_SET_TYPE = 0x20, 383 DAK_SUBRANGE_TYPE = 0x21, 384 DAK_WITH_STMT = 0x22, 385 DAK_ACCESS_DECLARATION = 0x23, 386 DAK_BASE_TYPE = 0x24, 387 DAK_CATCH_BLOCK = 0x25, 388 DAK_CONST_TYPE = 0x26, 389 DAK_CONSTANT = 0x27, 390 DAK_ENUMERATOR = 0x28, 391 DAK_FILE_TYPE = 0x29, 392 DAK_FRIEND = 0x2a, 393 DAK_NAMELIST = 0x2b, 394 DAK_NAMELIST_ITEM = 0x2c, 395 DAK_PACKED_TYPE = 0x2d, 396 DAK_SUBPROGRAM = 0x2e, 397 DAK_TEMPLATE_TYPE_PARAMETER = 0x2f, 398 DAK_TEMPLATE_VALUE_PARAMETER = 0x30, 399 DAK_THROWN_TYPE = 0x31, 400 DAK_TRY_BLOCK = 0x32, 401 DAK_VARIANT_PART = 0x33, 402 DAK_VARIABLE = 0x34, 403 DAK_VOLATILE_TYPE = 0x35, 404 DAK_DWARF_PROCEDURE = 0x36, 405 DAK_RESTRICT_TYPE = 0x37, 406 DAK_INTERFACE_TYPE = 0x38, 407 DAK_NAMESPACE = 0x39, 408 DAK_IMPORTED_MODULE = 0x3a, 409 DAK_UNSPECIFIED_TYPE = 0x3b, 410 DAK_PARTIAL_UNIT = 0x3c, 411 DAK_IMPORTED_UNIT = 0x3d, 412 DAK_CONDITION = 0x3f, 413 DAK_SHARED_TYPE = 0x40, 414 DAK_TYPE_UNIT = 0x41, 415 DAK_RVALUE_REFERENCE_TYPE = 0x42, 416 DAK_TEMPLATE_ALIAS = 0x43, 417 DAK_COARRAY_TYPE = 0x44, 418 DAK_GENERIC_SUBRANGE = 0x45, 419 DAK_DYNAMIC_TYPE = 0x46, 420 DAK_ATOMIC_TYPE = 0x47, 421 DAK_CALL_SITE = 0x48, 422 DAK_CALL_SITE_PARAMETER = 0x49, 423 DAK_SKELETON_UNIT = 0x4a, 424 DAK_IMMUTABLE_TYPE = 0x4b, 425 DAK_LO_USER = 0x4080, 426 DAK_HI_USER = 0xffff 427 } DWARFAbbreviationKind; 428 429 typedef struct DWARFAbbreviation { 430 DWARFAbbreviationKind kind; 431 b32 has_children; 432 u64 abbreviation_code; 433 434 DWARFAttribute *data; 435 s16 count; 436 s16 capacity; 437 438 struct DWARFAbbreviation *next; 439 } DWARFAbbreviation; 440 441 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 442 #error "reader functions not yet implemented for big endian hosts!" 443 #else 444 function u16 445 u16_host_from_be(u8 *s) 446 { 447 u16 result = 0; 448 result |= s[0]; result <<= 8; 449 result |= s[1]; 450 return result; 451 } 452 453 function u16 454 u16_host_from_le(u8 *s) 455 { 456 u16 result = 0; 457 result |= s[1]; result <<= 8; 458 result |= s[0]; 459 return result; 460 } 461 462 function u32 463 u32_host_from_be(u8 *s) 464 { 465 u32 result = 0; 466 result |= s[0]; result <<= 8; 467 result |= s[1]; result <<= 8; 468 result |= s[2]; result <<= 8; 469 result |= s[3]; 470 return result; 471 } 472 473 function u32 474 u32_host_from_le(u8 *s) 475 { 476 u32 result = 0; 477 result |= s[3]; result <<= 8; 478 result |= s[2]; result <<= 8; 479 result |= s[1]; result <<= 8; 480 result |= s[0]; 481 return result; 482 } 483 484 function u64 485 u64_host_from_be(u8 *s) 486 { 487 u64 result = 0; 488 result |= s[0]; result <<= 8; 489 result |= s[1]; result <<= 8; 490 result |= s[2]; result <<= 8; 491 result |= s[3]; result <<= 8; 492 result |= s[4]; result <<= 8; 493 result |= s[5]; result <<= 8; 494 result |= s[6]; result <<= 8; 495 result |= s[7]; 496 return result; 497 } 498 499 function u64 500 u64_host_from_le(u8 *s) 501 { 502 u64 result = 0; 503 result |= s[7]; result <<= 8; 504 result |= s[6]; result <<= 8; 505 result |= s[5]; result <<= 8; 506 result |= s[4]; result <<= 8; 507 result |= s[3]; result <<= 8; 508 result |= s[2]; result <<= 8; 509 result |= s[1]; result <<= 8; 510 result |= s[0]; 511 return result; 512 } 513 #endif 514 515 #define zero_struct(s) mem_clear(s, 0, sizeof(*s)); 516 function void * 517 mem_clear(void *restrict _s, u8 byte, iz size) 518 { 519 u8 *s = _s; 520 for (iz i = 0; i < size; i++) 521 s[i] = byte; 522 return s; 523 } 524 525 function void * 526 mem_copy(void *restrict dest, void *restrict src, iz size) 527 { 528 u8 *s = src, *d = dest; 529 for (iz i = 0; i < size; i++) 530 d[i] = s[i]; 531 return dest; 532 } 533 534 #define alloc(a, t, c) (t *)alloc_(a, _Alignof(t), sizeof(t), c) 535 function void * 536 alloc_(Arena *a, iz alignment, iz size, iz count) 537 { 538 iz capacity = a->end - a->beg; 539 iz padding = -(uintptr_t)a->beg & alignment; 540 if ((capacity - padding) / size < count) { 541 ASSERT(0 && "OOM: buy more ram lol"); 542 } 543 u8 *result = a->beg + padding; 544 a->beg += padding + size * count; 545 return mem_clear(result, 0, size * count); 546 } 547 548 enum { DA_INITIAL_CAP = 4 }; 549 #define da_reserve(a, s, n) \ 550 (s)->data = da_reserve_((a), (s)->data, &(s)->capacity, (s)->count + n, \ 551 _Alignof(typeof(*(s)->data)), sizeof(*(s)->data)) 552 553 #define da_push(a, s) \ 554 ((s)->count == (s)->capacity \ 555 ? da_reserve(a, s, 1), \ 556 (s)->data + (s)->count++ \ 557 : (s)->data + (s)->count++) 558 559 function void * 560 da_reserve_(Arena *a, void *data, s16 *capacity, iz needed, iz align, iz size) 561 { 562 iz cap = *capacity; 563 564 /* NOTE(rnp): handle both 0 initialized DAs and DAs that need to be moved (they started 565 * on the stack or someone allocated something in the middle of the arena during usage) */ 566 if (!data || a->beg != (u8 *)data + cap * size) { 567 void *copy = alloc_(a, size, align, cap); 568 if (data) mem_copy(copy, data, cap * size); 569 data = copy; 570 } 571 572 if (!cap) cap = DA_INITIAL_CAP; 573 while (cap < needed) cap *= 2; 574 alloc_(a, size, align, cap - *capacity); 575 *capacity = cap; 576 return data; 577 } 578 579 function str8 580 c_str_to_str8(u8 *c_str) 581 { 582 str8 result = {.data = c_str}; 583 if (c_str) while (*c_str) c_str++; 584 result.len = c_str - result.data; 585 return result; 586 } 587 588 function b32 589 str8_equal(str8 a, str8 b) 590 { 591 b32 result = a.len == b.len; 592 for (iz i = 0; result && i < a.len; i++) 593 result &= a.data[i] == b.data[i]; 594 return result; 595 } 596 597 function str8 598 str8_chop(str8 a, iz length) 599 { 600 str8 result = {0}; 601 if (length < a.len) { 602 result.data = a.data + length; 603 result.len = a.len - length; 604 } 605 return result; 606 } 607 608 function iz 609 str8_read_uleb128(str8 a, u64 *uleb128) 610 { 611 /* TODO(rnp): check for overflow ... */ 612 iz result = 0; 613 iz shift = 0; 614 u64 n = 0; 615 while (result < a.len) { 616 u8 byte = a.data[result++]; 617 n |= (u64)(byte & 0x7F) << shift; 618 if ((byte & 0x80) == 0) 619 break; 620 shift += 7; 621 } 622 *uleb128 = n; 623 return result; 624 } 625 626 function str8_reader 627 str8_reader_from_str8(str8 s) 628 { 629 str8_reader result = {0}; 630 result.data = s.data; 631 result.count = s.len; 632 return result; 633 } 634 635 function u16 636 str8_read_u16(str8_reader *r, b32 big_endian) 637 { 638 u16 result = 0; 639 r->errors |= r->index + 2 > r->count; 640 if (!r->errors) { 641 if (big_endian) result = u16_host_from_be(r->data + r->index); 642 else result = u16_host_from_le(r->data + r->index); 643 r->index += 2; 644 } 645 return result; 646 } 647 648 function u32 649 str8_read_u32(str8_reader *r, b32 big_endian) 650 { 651 u32 result = 0; 652 r->errors |= r->index + 4 > r->count; 653 if (!r->errors) { 654 if (big_endian) result = u32_host_from_be(r->data + r->index); 655 else result = u32_host_from_le(r->data + r->index); 656 r->index += 4; 657 } 658 return result; 659 } 660 661 function u64 662 str8_read_u64(str8_reader *r, b32 big_endian) 663 { 664 u64 result = 0; 665 r->errors |= r->index + 8 > r->count; 666 if (!r->errors) { 667 if (big_endian) result = u32_host_from_be(r->data + r->index); 668 else result = u32_host_from_le(r->data + r->index); 669 r->index += 8; 670 } 671 return result; 672 } 673 674 function void 675 print_u64(u64 v) 676 { 677 printf("%zu", v); 678 } 679 680 function void print_u16(u16 v) { print_u64(v); } 681 function void print_u32(u32 v) { print_u64(v); } 682 683 function void 684 print_ELFFormat(ELFFormat format) 685 { 686 #define X(name, value, pretty) [name] = str8(pretty), 687 local_persist str8 format_pretty[] = {ELF_FORMATS}; 688 #undef X 689 if (format < countof(format_pretty) && format_pretty[format].len) { 690 printf("%.*s", (s32)format_pretty[format].len, format_pretty[format].data); 691 } else { 692 printf("Invalid"); 693 } 694 } 695 696 function void 697 print_ELFEndianKind(ELFEndianKind kind) 698 { 699 #define X(name, value, pretty) [name] = str8(pretty), 700 local_persist str8 kind_pretty[] = {ELF_ENDIANNESS}; 701 #undef X 702 if (kind < countof(kind_pretty) && kind_pretty[kind].len) { 703 printf("%.*s", (s32)kind_pretty[kind].len, kind_pretty[kind].data); 704 } else { 705 printf("Invalid"); 706 } 707 } 708 709 function void 710 print_ELFABIKind(ELFABIKind kind) 711 { 712 #define X(name, value, pretty) [name] = str8(pretty), 713 local_persist str8 kind_pretty[] = {ELF_OS_ABI}; 714 #undef X 715 if (kind < countof(kind_pretty) && kind_pretty[kind].len) { 716 printf("%.*s", (s32)kind_pretty[kind].len, kind_pretty[kind].data); 717 } else { 718 printf("Invalid"); 719 } 720 } 721 722 function void 723 print_ELFKind(ELFKind kind) 724 { 725 #define X(name, value, pretty) [name] = str8(pretty), 726 local_persist str8 kind_pretty[] = {ELF_KINDS}; 727 #undef X 728 if (kind < countof(kind_pretty) && kind_pretty[kind].len) { 729 printf("%.*s", (s32)kind_pretty[kind].len, kind_pretty[kind].data); 730 } else { 731 printf("Invalid"); 732 } 733 } 734 735 function void 736 print_elf_header(ELFHeader *eh) 737 { 738 printf("ELF Header:\n"); 739 s32 max_name_len = 0; 740 #define X(ctype, name) if (max_name_len < sizeof(#name) - 1) max_name_len = sizeof(#name) - 1; 741 ELF_HEADER_MEMBERS 742 #undef X 743 744 #define X(ctype, name) printf(#name ": %*s", (s32)(max_name_len - sizeof(#name) + 1), ""); \ 745 print_##ctype(eh->name); printf("\n"); 746 ELF_HEADER_MEMBERS 747 #undef X 748 } 749 750 function b32 751 is_elf(str8 file) 752 { 753 b32 result = file.len >= 16; 754 result &= file.data[0] == 0x7F; 755 result &= file.data[1] == 'E'; 756 result &= file.data[2] == 'L'; 757 result &= file.data[3] == 'F'; 758 return result; 759 } 760 761 function b32 762 elf_header_from_file(ELFHeader *eh, str8 file) 763 { 764 b32 result = 0; 765 if (is_elf(file)) { 766 eh->format = file.data[4]; 767 eh->endianness = file.data[5]; 768 eh->abi = file.data[7]; 769 eh->abi_version = file.data[8]; 770 771 str8_reader reader = str8_reader_from_str8(str8_chop(file, 16)); 772 b32 big_endian = eh->endianness == EEK_BIG; 773 eh->kind = str8_read_u16(&reader, big_endian); 774 eh->machine = str8_read_u16(&reader, big_endian); 775 eh->version = str8_read_u32(&reader, big_endian); 776 if (eh->format == EF_64) { 777 eh->entry_point_offset = str8_read_u64(&reader, big_endian); 778 eh->program_header_offset = str8_read_u64(&reader, big_endian); 779 eh->section_header_offset = str8_read_u64(&reader, big_endian); 780 } else { 781 eh->entry_point_offset = str8_read_u32(&reader, big_endian); 782 eh->program_header_offset = str8_read_u32(&reader, big_endian); 783 eh->section_header_offset = str8_read_u32(&reader, big_endian); 784 } 785 eh->flags = str8_read_u32(&reader, big_endian); 786 eh->elf_header_size = str8_read_u16(&reader, big_endian); 787 eh->program_header_entry_size = str8_read_u16(&reader, big_endian); 788 eh->program_header_count = str8_read_u16(&reader, big_endian); 789 eh->section_header_entry_size = str8_read_u16(&reader, big_endian); 790 eh->section_header_count = str8_read_u16(&reader, big_endian); 791 eh->section_header_name_table_index = str8_read_u16(&reader, big_endian); 792 result = !reader.errors && file.data[6] == eh->version; 793 } 794 return result; 795 } 796 797 function ELFSectionHeader * 798 elf_extract_section_headers(Arena *a, str8 file, ELFHeader *eh) 799 { 800 TODO(eh->format == EF_64); 801 TODO(eh->endianness == EEK_LITTLE); 802 TODO(file.len >= eh->section_header_offset + eh->section_header_entry_size * eh->section_header_count); 803 u32 sections = eh->section_header_count; 804 ELFSectionHeader *result = alloc(a, ELFSectionHeader, sections); 805 for (u32 i = 0; i < sections; i++) { 806 iz offset = eh->section_header_offset + eh->section_header_entry_size * i; 807 result[i].sh64 = *(ELFSectionHeader64 *)(file.data + offset); 808 } 809 810 u8 *str_tab = file.data + result[eh->section_header_name_table_index].sh64.offset; 811 for (u32 i = 0; i < sections; i++) 812 result[i].name = c_str_to_str8(str_tab + result[i].sh64.name_table_offset); 813 814 return result; 815 } 816 817 function ELFSection 818 elf_lookup_section(str8 name, str8 file, ELFSectionHeader *shs, u32 sections_count) 819 { 820 ELFSection result = {0}; 821 for (u32 i = 0; i < sections_count; i++) { 822 if (str8_equal(shs[i].name, name)) { 823 result.header = shs + i; 824 result.store.data = file.data + shs[i].sh64.offset; 825 result.store.len = shs[i].sh64.size; 826 break; 827 } 828 } 829 return result; 830 } 831 832 function iz 833 dwarf_read_unit_header(DWARFUnitHeader *duh, str8 store) 834 { 835 iz result = 0; 836 /* TODO(rnp): context containing endianess, dwarf size */ 837 duh->dwarf_64 = *(u32 *)store.data == 0xffffffff; 838 if (duh->dwarf_64) { result += 12; duh->length = *(u64 *)(store.data + 4); } 839 else { result += 4; duh->length = *(u32 *)(store.data); } 840 duh->version = *(u16 *)(store.data + result); 841 result += 2; 842 if (duh->version == 5) duh->kind = store.data[result++]; 843 duh->address_size = store.data[result++]; 844 if (duh->dwarf_64) { duh->abbreviation_offset = *(u64 *)(store.data + result); result += 8; } 845 else { duh->abbreviation_offset = *(u32 *)(store.data + result); result += 4; } 846 return result; 847 } 848 849 function iz 850 dwarf_parse_abbrevation(Arena *a, DWARFAbbreviation *abbrv, str8 table) 851 { 852 iz table_start_size = table.len; 853 iz result = 0; 854 table = str8_chop(table, str8_read_uleb128(table, &abbrv->abbreviation_code)); 855 u64 abbrv_kind = 0; 856 table = str8_chop(table, str8_read_uleb128(table, &abbrv_kind)); 857 abbrv->kind = abbrv_kind; 858 if (table.len < 1) return table_start_size; 859 abbrv->has_children = *table.data; 860 table = str8_chop(table, 1); 861 for (;;) { 862 u64 attr_kind = 0, form_kind = 0; 863 table = str8_chop(table, str8_read_uleb128(table, &attr_kind)); 864 table = str8_chop(table, str8_read_uleb128(table, &form_kind)); 865 TODO(form_kind != DFK_INDIRECT); 866 TODO(form_kind != DFK_IMPLICIT_CONST); 867 if (attr_kind) { 868 *da_push(a, abbrv) = (DWARFAttribute){attr_kind, form_kind}; 869 } else { 870 ASSERT(form_kind == 0); 871 break; 872 } 873 } 874 result = table_start_size - table.len; 875 return result; 876 } 877 878 function DWARFAbbreviation 879 dwarf_lookup_abbreviation(Arena *a, str8 table, u64 key) 880 { 881 DWARFAbbreviation result = {0}; 882 while (key != result.abbreviation_code && table.len > 1) { 883 result.count = 0; 884 table = str8_chop(table, dwarf_parse_abbrevation(a, &result, table)); 885 } 886 return result; 887 } 888 889 function b32 890 elfinspect(Arena arena, str8 file) 891 { 892 b32 result = is_elf(file); 893 894 if (result) { 895 ELFHeader header = {0}; 896 if (!elf_header_from_file(&header, file)) { 897 return 1; 898 } 899 ELFSectionHeader *sections = elf_extract_section_headers(&arena, file, &header); 900 print_elf_header(&header); 901 printf("\nSections:\n"); 902 for (u32 i = 0; i < header.section_header_count; i++) { 903 printf("[%2u]:", i); 904 str8 name = sections[i].name; 905 if (name.len) printf(" %.*s", (s32)name.len, name.data); 906 printf("\n"); 907 } 908 909 ELFSection debug_info = elf_lookup_section(str8(".debug_info"), file, 910 sections, header.section_header_count); 911 ELFSection debug_abbrv = elf_lookup_section(str8(".debug_abbrev"), file, 912 sections, header.section_header_count); 913 ELFSection debug_str_offsets = elf_lookup_section(str8(".debug_str_offsets"), file, 914 sections, header.section_header_count); 915 ELFSection debug_str = elf_lookup_section(str8(".debug_str"), file, 916 sections, header.section_header_count); 917 918 str8 d_info_reader = debug_info.store; 919 DWARFUnitHeader d_info_header = {0}; 920 d_info_reader = str8_chop(d_info_reader, dwarf_read_unit_header(&d_info_header, d_info_reader)); 921 u64 abbreviation_code = 0; 922 str8 abbreviation_table = str8_chop(debug_abbrv.store, d_info_header.abbreviation_offset); 923 d_info_reader = str8_chop(d_info_reader, str8_read_uleb128(d_info_reader, &abbreviation_code)); 924 DWARFAbbreviation abbrv = dwarf_lookup_abbreviation(&arena, abbreviation_table, abbreviation_code); 925 926 printf("\nFirst DWARF DIE:\n"); 927 for (s16 i = 0; i < abbrv.count; i++) { 928 DWARFAttribute attr = abbrv.data[i]; 929 if (attr.kind == 0) 930 continue; 931 932 switch (attr.kind) { 933 case DATK_PRODUCER: printf("producer: "); break; 934 case DATK_LANGUAGE: printf("language: "); break; 935 case DATK_ADDR_BASE: printf("addr base: "); break; 936 case DATK_LOCLISTS_BASE: printf("loc list base: "); break; 937 default: ASSERT(0); break; 938 } 939 940 switch (attr.form_kind) { 941 case DFK_STRX1: { 942 u32 str_offset_offset = *d_info_reader.data; 943 d_info_reader = str8_chop(d_info_reader, 1); 944 u32 str_offset = *(u32 *)(debug_str_offsets.store.data + str_offset_offset); 945 printf("%s", (char *)debug_str.store.data + str_offset); 946 } break; 947 case DFK_DATA2: { 948 u32 data = *(u16 *)d_info_reader.data; 949 d_info_reader = str8_chop(d_info_reader, 2); 950 printf("%u", data); 951 } break; 952 case DFK_SEC_OFFSET: { 953 u32 data = *(u32 *)d_info_reader.data; 954 d_info_reader = str8_chop(d_info_reader, 4); 955 printf("%u", data); 956 } break; 957 default: ASSERT(0); break; 958 } 959 printf("\n"); 960 } 961 962 result = 1; 963 } 964 965 return result; 966 }