1 #include <fixdwarf.h> 2 #include <common.h> 3 #include <debug.h> 4 #include <hash.h> 5 6 #include <libelf.h> 7 #include <libebl.h> 8 #include <libebl_arm.h> 9 10 #include <stdio.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <string.h> 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include <fcntl.h> 17 #include <unistd.h> 18 19 /* When this macro is set to a nonzero value, we maintain a BST where we store each address once 20 we update the value at that address, and check to make sure that the address has not been 21 visited before we udpate it. This way we make sure that we do not do multiple updates at any 22 any given address. The feature is disabled by default because it is very expensive. It should 23 be enabled as a first step in debugging problems with the DWARF patches that this code makes. 24 */ 25 26 #define PARANOIA (0) 27 28 #define _str(name) #name 29 #define _id(a,b) a ## b 30 31 #if PARANOIA 32 #define COLLECT_BACKTRACES (0) 33 34 #if COLLECT_BACKTRACES 35 #include <execinfo.h> 36 #endif 37 #endif/*PARANOIA*/ 38 39 #include <dwarf.h> 40 41 int load_debug_section (enum dwarf_section_display_enum debug, void *file); 42 void free_debug_section (enum dwarf_section_display_enum debug); 43 44 static shdr_info_t *s_shdr_info; 45 static int s_shdr_info_len; 46 static int dwarf_to_shdr[max]; 47 static shdr_info_t *s_cached_find_section_result = NULL; 48 static int s_num_total_patches = 0; 49 static int s_num_failed_patches = 0; 50 51 static void init_value_free_lists(); 52 53 #if PARANOIA 54 typedef struct value_struct { 55 unsigned long key; 56 struct value_struct *left; 57 struct value_struct *right; 58 #if COLLECT_BACKTRACES 59 #define BACKTRACE_DEPTH (10) 60 void *backtrace[BACKTRACE_DEPTH]; 61 int backtrace_depth; 62 #endif/*COLLECT_BACKTRACES*/ 63 } value_t; 64 65 static value_t *s_visited_values; /* BST of visited values */ 66 #endif/*PARANOIA*/ 67 68 static void dump_dwarf_section (enum dwarf_section_display_enum dwarf_idx); 69 static void byte_set_little_endian ( 70 unsigned char *field, int size, dwarf_vma val); 71 static void byte_set_big_endian ( 72 unsigned char *field, int size, dwarf_vma val); 73 static void (*byte_set) (unsigned char *, int, dwarf_vma); 74 75 void update_dwarf_if_necessary(Elf *elf __attribute__((unused)), 76 GElf_Ehdr *ehdr, 77 Elf *newelf __attribute__((unused)), 78 shdr_info_t *shdr_info, int num_shdr_info, 79 int *num_total_patches, int *num_failed_patches) 80 { 81 /* Find the debug sections */ 82 83 int cnt; 84 85 /* Initialize the static variables, which might have been left in 86 nondefault states from a previous call to this function. 87 */ 88 s_shdr_info = NULL; 89 s_cached_find_section_result = NULL; 90 s_shdr_info_len = 0; 91 s_num_total_patches = 0; 92 s_num_failed_patches = 0; 93 memset(dwarf_to_shdr, 0, sizeof(dwarf_to_shdr)); 94 for(cnt = 0; cnt < max; cnt++) 95 free_debug_section(cnt); 96 #if PARANOIA 97 s_visited_values = NULL; 98 init_value_free_lists(); 99 #endif/*PARANOIA*/ 100 init_dwarf_variables(); 101 102 cnt = 0; 103 104 /* Locate the .debug_<xxx> sections, and save 105 their indices (in shdr_info) in the respective 106 idx_debug_<xxx> variable. If a section is not 107 prwesent in the file, the variable will have 108 a negative value after this loop. 109 */ 110 111 #define CHECK_DEBUG_SECTION(sname) \ 112 ASSERT(shdr_info[cnt].name != NULL); \ 113 if (!strcmp(shdr_info[cnt].name, \ 114 ".debug_" _str(sname))) { \ 115 FAILIF(dwarf_to_shdr[sname] > 0, \ 116 ".debug_" _str(sname) " is already found at index %d!\n", \ 117 dwarf_to_shdr[sname]); \ 118 INFO("Index of \".debug_" _str(name) " is %d", cnt); \ 119 if (shdr_info[cnt].idx > 0) \ 120 dwarf_to_shdr[sname] = cnt; \ 121 else INFO(", but the section is being removed."); \ 122 INFO("\n"); \ 123 } 124 125 for(cnt = 1; cnt < num_shdr_info; cnt++) { 126 CHECK_DEBUG_SECTION(aranges); 127 CHECK_DEBUG_SECTION(info); 128 CHECK_DEBUG_SECTION(abbrev); 129 CHECK_DEBUG_SECTION(line); 130 CHECK_DEBUG_SECTION(frame); 131 CHECK_DEBUG_SECTION(loc); 132 CHECK_DEBUG_SECTION(ranges); 133 CHECK_DEBUG_SECTION(pubnames); 134 CHECK_DEBUG_SECTION(str); 135 } 136 #undef CHECK_DEBUG_SECTION 137 138 { 139 is_relocatable = (ehdr->e_type == ET_REL); 140 eh_addr_size = 4; 141 142 if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) { 143 byte_get = byte_get_little_endian; 144 byte_set = byte_set_little_endian; 145 } 146 else { 147 ASSERT(ehdr->e_ident[EI_DATA] == ELFDATA2MSB); 148 byte_get = byte_get_big_endian; 149 byte_set = byte_set_big_endian; 150 } 151 } 152 153 #define ADJUST_IF_NECESSARY(sname) \ 154 do { \ 155 if (dwarf_to_shdr[sname] > 0) { \ 156 INFO("\nAdjusting for %s.\n", shdr_info[dwarf_to_shdr[sname]].name); \ 157 dump_dwarf_section(sname); \ 158 } \ 159 else { \ 160 INFO("\nNot adjusting for %s.\n", shdr_info[dwarf_to_shdr[sname]].name); \ 161 } \ 162 } while(0) 163 164 s_shdr_info = shdr_info; 165 s_shdr_info_len = num_shdr_info; 166 167 ADJUST_IF_NECESSARY(info); 168 ADJUST_IF_NECESSARY(loc); 169 ADJUST_IF_NECESSARY(aranges); 170 ADJUST_IF_NECESSARY(frame); 171 ADJUST_IF_NECESSARY(ranges); 172 ADJUST_IF_NECESSARY(line); 173 ADJUST_IF_NECESSARY(str); 174 ADJUST_IF_NECESSARY(pubnames); 175 ADJUST_IF_NECESSARY(abbrev); 176 177 #undef ADJUST_IF_NECESSRY 178 179 *num_total_patches = s_num_total_patches; 180 *num_failed_patches = s_num_failed_patches; 181 } 182 183 int 184 load_debug_section (enum dwarf_section_display_enum debug, 185 void *file __attribute__((unused))) 186 { 187 struct dwarf_section *section = &debug_displays [debug].section; 188 int shdr_idx = dwarf_to_shdr[debug]; 189 if (!shdr_idx) { 190 INFO("Could not load section %s: it is not in the file.\n", 191 debug_displays[debug].section.name); 192 return 0; 193 } 194 ASSERT(s_shdr_info); 195 196 INFO("Loading DWARF section type %s index %d (type %d)\n", 197 s_shdr_info[shdr_idx].name, 198 s_shdr_info[shdr_idx].idx, 199 debug); 200 201 /* If it is already loaded, do nothing. */ 202 if (section->start != NULL) { 203 INFO("\tAlready loaded DWARF section type %s (type %d)\n", s_shdr_info[shdr_idx].name, debug); 204 return 1; 205 } 206 207 ASSERT(s_shdr_info[shdr_idx].newdata); 208 209 section->address = s_shdr_info[shdr_idx].shdr.sh_addr; 210 section->start = s_shdr_info[shdr_idx].newdata->d_buf; 211 section->size = s_shdr_info[shdr_idx].newdata->d_size; 212 ASSERT(s_shdr_info[shdr_idx].newdata->d_off == 0); 213 214 ASSERT(section->size != 0); 215 ASSERT(s_shdr_info[shdr_idx].shdr.sh_size == s_shdr_info[shdr_idx].newdata->d_size); 216 ASSERT(section->start != NULL); 217 218 return 1; 219 } 220 221 void 222 free_debug_section (enum dwarf_section_display_enum debug) 223 { 224 struct dwarf_section *section = &debug_displays [debug].section; 225 226 INFO("Unloading DWARF section type %d\n", debug); 227 228 if (section->start == NULL) 229 return; 230 231 section->start = NULL; 232 section->address = 0; 233 section->size = 0; 234 } 235 236 static void 237 dump_dwarf_section (enum dwarf_section_display_enum dwarf_idx) 238 { 239 int shdr_idx = dwarf_to_shdr[dwarf_idx]; 240 ASSERT(shdr_idx); 241 ASSERT(s_shdr_info); 242 ASSERT(s_shdr_info[shdr_idx].idx); 243 ASSERT(s_shdr_info[shdr_idx].name); 244 245 ASSERT(!strcmp (debug_displays[dwarf_idx].section.name, s_shdr_info[shdr_idx].name)); 246 247 if (!debug_displays[dwarf_idx].eh_frame) { 248 struct dwarf_section *sec = &debug_displays [dwarf_idx].section; 249 250 if (load_debug_section (dwarf_idx, NULL)) { 251 INFO("Dumping DWARF section [%s] (type %d).\n", 252 s_shdr_info[shdr_idx].name, 253 dwarf_idx); 254 debug_displays[dwarf_idx].display (sec, NULL); 255 if (dwarf_idx != info && dwarf_idx != abbrev) 256 free_debug_section (dwarf_idx); 257 } 258 } 259 } 260 261 static shdr_info_t *find_section(int value) 262 { 263 ASSERT(s_shdr_info != NULL); 264 ASSERT(s_shdr_info_len > 0); 265 266 #define IN_RANGE(v,s,l) ((s)<=(v) && (v)<((s)+(l))) 267 if (s_cached_find_section_result != NULL && 268 IN_RANGE((unsigned)value, 269 s_cached_find_section_result->old_shdr.sh_addr, 270 s_cached_find_section_result->old_shdr.sh_size)) { 271 return s_cached_find_section_result; 272 } 273 274 /* Find the section to which the address belongs. */ 275 int cnt; 276 for (cnt = 0; cnt < s_shdr_info_len; cnt++) { 277 if (s_shdr_info[cnt].idx > 0 && 278 (s_shdr_info[cnt].old_shdr.sh_flags & SHF_ALLOC) && 279 IN_RANGE((unsigned) value, 280 s_shdr_info[cnt].old_shdr.sh_addr, 281 s_shdr_info[cnt].old_shdr.sh_size)) { 282 283 s_cached_find_section_result = s_shdr_info + cnt; 284 return s_cached_find_section_result; 285 } 286 } 287 #undef IN_RANGE 288 289 return NULL; 290 } 291 292 #if PARANOIA 293 static value_t **s_value_free_lists; 294 static int s_num_free_lists; 295 static int s_cur_free_list; 296 static int s_alloc_values; /* number of allocated values in the list */ 297 #define LISTS_INCREMENT (10) 298 #define NUM_VALUES_PER_LIST (10000) 299 300 static void init_value_free_lists() 301 { 302 if (s_value_free_lists) { 303 value_t **trav = s_value_free_lists; 304 while(s_cur_free_list) { 305 FREE(*trav++); 306 s_cur_free_list--; 307 } 308 FREE(s_value_free_lists); 309 s_value_free_lists = NULL; 310 } 311 s_num_free_lists = 0; 312 s_alloc_values = 0; 313 } 314 315 static value_t *alloc_value() 316 { 317 if (s_alloc_values == NUM_VALUES_PER_LIST) { 318 s_cur_free_list++; 319 s_alloc_values = 0; 320 } 321 322 if (s_cur_free_list == s_num_free_lists) { 323 s_num_free_lists += LISTS_INCREMENT; 324 s_value_free_lists = REALLOC(s_value_free_lists, 325 s_num_free_lists * sizeof(value_t *)); 326 memset(s_value_free_lists + s_cur_free_list, 327 0, 328 (s_num_free_lists - s_cur_free_list) * sizeof(value_t *)); 329 } 330 331 if (s_value_free_lists[s_cur_free_list] == NULL) { 332 s_value_free_lists[s_cur_free_list] = MALLOC(NUM_VALUES_PER_LIST*sizeof(value_t)); 333 } 334 335 return s_value_free_lists[s_cur_free_list] + s_alloc_values++; 336 } 337 338 static value_t *would_be_parent = NULL; 339 static value_t *find_value(unsigned long val) 340 { 341 would_be_parent = NULL; 342 value_t *trav = s_visited_values; 343 while(trav) { 344 would_be_parent = trav; 345 if (val < trav->key) 346 trav = trav->left; 347 else if (val > trav->key) 348 trav = trav->right; 349 else if (val == trav->key) { 350 return trav; 351 } 352 } 353 return NULL; 354 } 355 356 static int value_visited(unsigned long val) 357 { 358 value_t *found = find_value(val); 359 if (found != NULL) { 360 #if COLLECT_BACKTRACES 361 void *new_bt[BACKTRACE_DEPTH]; 362 int new_bt_depth = backtrace(new_bt, BACKTRACE_DEPTH); 363 char **symbols = backtrace_symbols(new_bt, new_bt_depth); 364 PRINT("NEW VISIT AT %x\n", val); 365 if (symbols != NULL) { 366 int cnt = 0; 367 while(cnt < new_bt_depth) { 368 PRINT("\t%s\n", symbols[cnt]); 369 cnt++; 370 } 371 } 372 FREE(symbols); 373 PRINT("OLD VISIT AT %x\n", val); 374 symbols = backtrace_symbols(found->backtrace, found->backtrace_depth); 375 if (symbols != NULL) { 376 int cnt = 0; 377 while(cnt < new_bt_depth) { 378 PRINT("\t%s\n", symbols[cnt]); 379 cnt++; 380 } 381 } 382 FREE(symbols); 383 #else 384 ERROR("DWARF: Double update at address 0x%lx!\n", val); 385 #endif/*COLLECT_BACKTRACES*/ 386 return 1; 387 } 388 found = alloc_value(); 389 found->left = found->right = NULL; 390 found->key = val; 391 #if COLLECT_BACKTRACES 392 found->backtrace_depth = backtrace(found->backtrace, BACKTRACE_DEPTH); 393 #endif/*COLLECT_BACKTRACES*/ 394 if (would_be_parent == NULL) { 395 s_visited_values = found; 396 } else { 397 if (val < would_be_parent->key) 398 would_be_parent->left = found; 399 else 400 would_be_parent->right = found; 401 } 402 return 0; 403 } 404 #else 405 static int value_visited(unsigned long val __attribute__((unused))) 406 { 407 return 0; 408 } 409 #endif /*PARANOIA*/ 410 411 void value_hook(void *data, int size, int val) 412 { 413 shdr_info_t *shdr = find_section(val); 414 s_num_total_patches++; 415 if(shdr == NULL) { 416 PRINT("DWARF: cannot map address 0x%x to any section!\n", val); 417 s_num_failed_patches++; 418 return; 419 } 420 long delta = shdr->shdr.sh_addr - shdr->old_shdr.sh_addr; 421 if(delta) { 422 if (!value_visited((unsigned long)data)) { 423 INFO("DWARF: adjusting %d-byte value at %p: 0x%x -> 0x%x (delta %d per section %s)\n", 424 size, data, 425 val, (int)(val + delta), (int)delta, 426 shdr->name); 427 byte_set(data, size, val + delta); 428 } 429 } 430 } 431 432 void base_value_pair_hook(void *data, int size, 433 int base, int begin, int end) 434 { 435 shdr_info_t *shdr = find_section(base + begin); 436 s_num_total_patches++; 437 438 if (begin > end) { 439 PRINT("DWARF: start > end in range 0x%x:[0x%x, 0x%x)!\n", 440 base, 441 begin, 442 end); 443 s_num_failed_patches++; 444 return; 445 } 446 447 if(shdr == NULL) { 448 PRINT("DWARF: cannot map range 0x%x:[0x%x, 0x%x) to any section!\n", 449 base, 450 begin, 451 end); 452 s_num_failed_patches++; 453 return; 454 } 455 456 if (unlikely(begin != end)) { 457 shdr_info_t *end_shdr = find_section(base + end - 1); 458 if (shdr != end_shdr) { 459 printf("DWARF: range 0x%x:[%x, %x) maps to different sections: %s and %s!\n", 460 base, 461 begin, end, 462 shdr->name, 463 (end_shdr ? end_shdr->name : "(none)")); 464 s_num_failed_patches++; 465 return; 466 } 467 } 468 469 long delta = shdr->shdr.sh_addr - shdr->old_shdr.sh_addr; 470 if(delta) { 471 if (!value_visited((unsigned long)data)) { 472 INFO("DWARF: adjusting %d-byte value at %p: 0x%x -> 0x%x (delta %d per section %s)\n", 473 size, data, 474 begin, (int)(begin + delta), (int)delta, 475 shdr->name); 476 byte_set(data, size, begin + delta); 477 byte_set(data + size, size, end + delta); 478 } 479 } 480 } 481 482 void signed_value_hook( 483 void *data, 484 int pointer_size, 485 int is_signed, 486 int value) 487 { 488 INFO("DWARF frame info: initial PC value: %8x (width %d), %ssigned\n", 489 value, pointer_size, 490 (!is_signed ? "un" : "")); 491 492 ASSERT(s_shdr_info != NULL); 493 494 /* Find the section to which the address belongs. */ 495 shdr_info_t *shdr = find_section(value); 496 s_num_total_patches++; 497 if(shdr == NULL) { 498 PRINT("DWARF: cannot map address 0x%x to any section!\n", value); 499 s_num_failed_patches++; 500 return; 501 } 502 503 long delta = shdr->shdr.sh_addr - shdr->old_shdr.sh_addr; 504 505 INFO("DWARF frame info: initial PC value: 0x%lx -> 0x%lx (delta %ld per section %s).\n", 506 (long)value, 507 (long)(value + delta), 508 delta, 509 shdr->name); 510 511 if (delta) { 512 if (!value_visited((unsigned long)data)) { 513 value += delta; 514 if (is_signed) { 515 switch (pointer_size) { 516 case 1: 517 value &= 0xFF; 518 value = (value ^ 0x80) - 0x80; 519 break; 520 case 2: 521 value &= 0xFFFF; 522 value = (value ^ 0x8000) - 0x8000; 523 break; 524 case 4: 525 value &= 0xFFFFFFFF; 526 value = (value ^ 0x80000000) - 0x80000000; 527 break; 528 case 8: 529 break; 530 default: 531 FAILIF(1, "Unsupported data size %d!\n", pointer_size); 532 } 533 } 534 byte_set(data, pointer_size, value); 535 } 536 } 537 } 538 539 static void byte_set_little_endian (unsigned char *field, int size, dwarf_vma val) 540 { 541 switch (size) { 542 case 1: 543 FAILIF(val > 0xFF, 544 "Attempting to set value 0x%lx to %d-bit integer!\n", 545 val, size*8); 546 *((uint8_t *)field) = (uint8_t)val; 547 break; 548 case 2: 549 FAILIF(val > 0xFFFF, 550 "Attempting to set value 0x%lx to %d-bit integer!\n", 551 val, size*8); 552 field[1] = (uint8_t)(val >> 8); 553 field[0] = (uint8_t)val; 554 break; 555 case 4: 556 #if 0 557 // this will signal false negatives when running on a 64 bit system. 558 FAILIF(val > 0xFFFFFFFF, 559 "Attempting to set value 0x%lx to %d-bit integer!\n", 560 val, size*8); 561 #endif 562 field[3] = (uint8_t)(val >> 23); 563 field[2] = (uint8_t)(val >> 16); 564 field[1] = (uint8_t)(val >> 8); 565 field[0] = (uint8_t)val; 566 break; 567 default: 568 FAILIF(1, "Unhandled data length: %d\n", size); 569 } 570 } 571 572 static void byte_set_big_endian (unsigned char *field __attribute__((unused)), 573 int size __attribute__((unused)), 574 dwarf_vma val __attribute__((unused))) 575 { 576 FAILIF(1, "Not implemented.\n"); 577 } 578