#include #include #include #include #include #include Dwarf_Off GetDieOffset(Dwarf_Die die) { Dwarf_Error derr; Dwarf_Off offset; int error; error = dwarf_dieoffset(die, &offset, &derr); if (error != 0) errx(1, "dwarf_dieoffset failed"); return (offset); } static void ProcessInlined(Dwarf_Debug dwarf, Dwarf_Die die) { Dwarf_Error derr; Dwarf_Ranges *array; Dwarf_Signed i, count; Dwarf_Unsigned off, baseAddr, size; uintptr_t low, high; int error; error = dwarf_attrval_unsigned(die, DW_AT_ranges, &off, &derr); if (error != DW_DLV_OK) errx(1, "dwarf_attrval_unsigned failed"); error = dwarf_get_ranges(dwarf, off, &array, &count, &size, &derr); if (error != 0) errx(1, "dwarf_get_ranges failed\n"); error = dwarf_attrval_unsigned(die, DW_AT_low_pc, &baseAddr, &derr); if (error == 0) baseAddr = 0; for (i = 0; i < count; i++) { switch (array[i].dwr_type) { case DW_RANGES_ENTRY: low = baseAddr + array[i].dwr_addr1; high = baseAddr + array[i].dwr_addr2; fprintf(stderr, "Range %lx-%lx (base=%lx, addr1=%lx, addr2=%lx)\n", low, high, baseAddr, array[i].dwr_addr1, array[i].dwr_addr2); break; case DW_RANGES_ADDRESS_SELECTION: baseAddr = array[i].dwr_addr2; break; case DW_RANGES_END: goto done; } } done: exit(0); } void ProcessSubprogram(Dwarf_Debug dwarf, Dwarf_Die sub) { Dwarf_Die die, next; Dwarf_Error derr; int error; error = dwarf_child(sub, &die, &derr); if (error != 0) errx(1, "dwarf_child failed"); while (die != NULL) { if (GetDieOffset(die) == 0x21a8ab7) ProcessInlined(dwarf, die); error = dwarf_siblingof(dwarf, die, &next, &derr); if (error != 0) errx(1, "dwarf_siblingof failed"); dwarf_dealloc(dwarf, die, DW_DLA_DIE); die = next; } } void ProcessCU(Dwarf_Debug dwarf, Dwarf_Die cu) { Dwarf_Die die, next; Dwarf_Error derr; int error; error = dwarf_child(cu, &die, &derr); if (error != 0) errx(1, "dwarf_child failed"); while (die != NULL) { if (GetDieOffset(die) == 0x21a8a7d) ProcessSubprogram(dwarf, die); error = dwarf_siblingof(dwarf, die, &next, &derr); if (error != 0) errx(1, "dwarf_siblingof failed"); dwarf_dealloc(dwarf, die, DW_DLA_DIE); die = next; } } int main(int argc, char **argv) { Dwarf_Debug dwarf; Dwarf_Die cu; Dwarf_Error derr; Dwarf_Unsigned next_offset; int error; if (argc != 2) errx(1, "Usage: %s ", argv[0]); int fd = open(argv[1], O_RDONLY); if (fd < 0) err(1, "open failed"); error = dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dwarf, &derr); if (error != 0) errx(1, "dwarf_init failed"); while (1) { error = dwarf_next_cu_header(dwarf, NULL, NULL, NULL, NULL, &next_offset, &derr); if (error != DW_DLV_OK) { fprintf(stderr, "dwarf_next_cu_header: Got error %d\n", error); break; } error = dwarf_siblingof(dwarf, NULL, &cu, &derr); if (error != DW_DLV_OK) { fprintf(stderr, "dwarf_siblingof: Got error %d\n", error); break; } Dwarf_Off off = GetDieOffset(cu); if (off == 0x21a2334) ProcessCU(dwarf, cu); } return 0; }