aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2013-04-12 16:13:42 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-04-16 18:19:06 -0400
commitbf11655cf2ecdcfaacbc8324da4a3edfe276ba9d (patch)
treea761d2f887cc64074539aca775743dc108d59394
parent4eefbe792baedb474e256d35370849992fcf1c79 (diff)
x86, relocs: Generalize ELF structure names
In preparation for making the reloc tool operate on 64-bit relocations, generalize the structure names for easy recompilation via #defines. Based on work by Neill Clift and Michael Davidson. Signed-off-by: Kees Cook <keescook@chromium.org> Link: http://lkml.kernel.org/r/1365797627-20874-2-git-send-email-keescook@chromium.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/tools/relocs.c170
1 files changed, 99 insertions, 71 deletions
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 79d67bd507fa..fd28ef7dfbb9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -12,20 +12,42 @@
12#include <regex.h> 12#include <regex.h>
13#include <tools/le_byteshift.h> 13#include <tools/le_byteshift.h>
14 14
15#define ElfW(type) _ElfW(ELF_BITS, type)
16#define _ElfW(bits, type) __ElfW(bits, type)
17#define __ElfW(bits, type) Elf##bits##_##type
18
19#define ELF_BITS 32
20#define ELF_MACHINE EM_386
21#define ELF_MACHINE_NAME "i386"
22#define SHT_REL_TYPE SHT_REL
23
24#define ELF_CLASS ELFCLASS32
25#define ELF_R_SYM(val) ELF32_R_SYM(val)
26#define ELF_R_TYPE(val) ELF32_R_TYPE(val)
27#define ELF_ST_TYPE(o) ELF32_ST_TYPE(o)
28#define ELF_ST_BIND(o) ELF32_ST_BIND(o)
29#define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o)
30
31#define Elf_Rel ElfW(Rel)
32#define Elf_Ehdr ElfW(Ehdr)
33#define Elf_Phdr ElfW(Phdr)
34#define Elf_Shdr ElfW(Shdr)
35#define Elf_Sym ElfW(Sym)
36
15static void die(char *fmt, ...); 37static void die(char *fmt, ...);
16 38
17#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 39#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
18static Elf32_Ehdr ehdr; 40static Elf_Ehdr ehdr;
19static unsigned long reloc_count, reloc_idx; 41static unsigned long reloc_count, reloc_idx;
20static unsigned long *relocs; 42static unsigned long *relocs;
21static unsigned long reloc16_count, reloc16_idx; 43static unsigned long reloc16_count, reloc16_idx;
22static unsigned long *relocs16; 44static unsigned long *relocs16;
23 45
24struct section { 46struct section {
25 Elf32_Shdr shdr; 47 Elf_Shdr shdr;
26 struct section *link; 48 struct section *link;
27 Elf32_Sym *symtab; 49 Elf_Sym *symtab;
28 Elf32_Rel *reltab; 50 Elf_Rel *reltab;
29 char *strtab; 51 char *strtab;
30}; 52};
31static struct section *secs; 53static struct section *secs;
@@ -240,7 +262,7 @@ static const char *sec_name(unsigned shndx)
240 return name; 262 return name;
241} 263}
242 264
243static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) 265static const char *sym_name(const char *sym_strtab, Elf_Sym *sym)
244{ 266{
245 const char *name; 267 const char *name;
246 name = "<noname>"; 268 name = "<noname>";
@@ -274,6 +296,12 @@ static uint32_t elf32_to_cpu(uint32_t val)
274 return le32_to_cpu(val); 296 return le32_to_cpu(val);
275} 297}
276 298
299#define elf_half_to_cpu(x) elf16_to_cpu(x)
300#define elf_word_to_cpu(x) elf32_to_cpu(x)
301#define elf_addr_to_cpu(x) elf32_to_cpu(x)
302#define elf_off_to_cpu(x) elf32_to_cpu(x)
303#define elf_xword_to_cpu(x) elf32_to_cpu(x)
304
277static void read_ehdr(FILE *fp) 305static void read_ehdr(FILE *fp)
278{ 306{
279 if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { 307 if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
@@ -283,8 +311,8 @@ static void read_ehdr(FILE *fp)
283 if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) { 311 if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
284 die("No ELF magic\n"); 312 die("No ELF magic\n");
285 } 313 }
286 if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { 314 if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) {
287 die("Not a 32 bit executable\n"); 315 die("Not a %d bit executable\n", ELF_BITS);
288 } 316 }
289 if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { 317 if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
290 die("Not a LSB ELF executable\n"); 318 die("Not a LSB ELF executable\n");
@@ -293,36 +321,36 @@ static void read_ehdr(FILE *fp)
293 die("Unknown ELF version\n"); 321 die("Unknown ELF version\n");
294 } 322 }
295 /* Convert the fields to native endian */ 323 /* Convert the fields to native endian */
296 ehdr.e_type = elf16_to_cpu(ehdr.e_type); 324 ehdr.e_type = elf_half_to_cpu(ehdr.e_type);
297 ehdr.e_machine = elf16_to_cpu(ehdr.e_machine); 325 ehdr.e_machine = elf_half_to_cpu(ehdr.e_machine);
298 ehdr.e_version = elf32_to_cpu(ehdr.e_version); 326 ehdr.e_version = elf_word_to_cpu(ehdr.e_version);
299 ehdr.e_entry = elf32_to_cpu(ehdr.e_entry); 327 ehdr.e_entry = elf_addr_to_cpu(ehdr.e_entry);
300 ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff); 328 ehdr.e_phoff = elf_off_to_cpu(ehdr.e_phoff);
301 ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff); 329 ehdr.e_shoff = elf_off_to_cpu(ehdr.e_shoff);
302 ehdr.e_flags = elf32_to_cpu(ehdr.e_flags); 330 ehdr.e_flags = elf_word_to_cpu(ehdr.e_flags);
303 ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize); 331 ehdr.e_ehsize = elf_half_to_cpu(ehdr.e_ehsize);
304 ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize); 332 ehdr.e_phentsize = elf_half_to_cpu(ehdr.e_phentsize);
305 ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum); 333 ehdr.e_phnum = elf_half_to_cpu(ehdr.e_phnum);
306 ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize); 334 ehdr.e_shentsize = elf_half_to_cpu(ehdr.e_shentsize);
307 ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum); 335 ehdr.e_shnum = elf_half_to_cpu(ehdr.e_shnum);
308 ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx); 336 ehdr.e_shstrndx = elf_half_to_cpu(ehdr.e_shstrndx);
309 337
310 if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { 338 if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
311 die("Unsupported ELF header type\n"); 339 die("Unsupported ELF header type\n");
312 } 340 }
313 if (ehdr.e_machine != EM_386) { 341 if (ehdr.e_machine != ELF_MACHINE) {
314 die("Not for x86\n"); 342 die("Not for %s\n", ELF_MACHINE_NAME);
315 } 343 }
316 if (ehdr.e_version != EV_CURRENT) { 344 if (ehdr.e_version != EV_CURRENT) {
317 die("Unknown ELF version\n"); 345 die("Unknown ELF version\n");
318 } 346 }
319 if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) { 347 if (ehdr.e_ehsize != sizeof(Elf_Ehdr)) {
320 die("Bad Elf header size\n"); 348 die("Bad Elf header size\n");
321 } 349 }
322 if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { 350 if (ehdr.e_phentsize != sizeof(Elf_Phdr)) {
323 die("Bad program header entry\n"); 351 die("Bad program header entry\n");
324 } 352 }
325 if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) { 353 if (ehdr.e_shentsize != sizeof(Elf_Shdr)) {
326 die("Bad section header entry\n"); 354 die("Bad section header entry\n");
327 } 355 }
328 if (ehdr.e_shstrndx >= ehdr.e_shnum) { 356 if (ehdr.e_shstrndx >= ehdr.e_shnum) {
@@ -333,7 +361,7 @@ static void read_ehdr(FILE *fp)
333static void read_shdrs(FILE *fp) 361static void read_shdrs(FILE *fp)
334{ 362{
335 int i; 363 int i;
336 Elf32_Shdr shdr; 364 Elf_Shdr shdr;
337 365
338 secs = calloc(ehdr.e_shnum, sizeof(struct section)); 366 secs = calloc(ehdr.e_shnum, sizeof(struct section));
339 if (!secs) { 367 if (!secs) {
@@ -349,16 +377,16 @@ static void read_shdrs(FILE *fp)
349 if (fread(&shdr, sizeof shdr, 1, fp) != 1) 377 if (fread(&shdr, sizeof shdr, 1, fp) != 1)
350 die("Cannot read ELF section headers %d/%d: %s\n", 378 die("Cannot read ELF section headers %d/%d: %s\n",
351 i, ehdr.e_shnum, strerror(errno)); 379 i, ehdr.e_shnum, strerror(errno));
352 sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name); 380 sec->shdr.sh_name = elf_word_to_cpu(shdr.sh_name);
353 sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type); 381 sec->shdr.sh_type = elf_word_to_cpu(shdr.sh_type);
354 sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags); 382 sec->shdr.sh_flags = elf_xword_to_cpu(shdr.sh_flags);
355 sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr); 383 sec->shdr.sh_addr = elf_addr_to_cpu(shdr.sh_addr);
356 sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset); 384 sec->shdr.sh_offset = elf_off_to_cpu(shdr.sh_offset);
357 sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size); 385 sec->shdr.sh_size = elf_xword_to_cpu(shdr.sh_size);
358 sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link); 386 sec->shdr.sh_link = elf_word_to_cpu(shdr.sh_link);
359 sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info); 387 sec->shdr.sh_info = elf_word_to_cpu(shdr.sh_info);
360 sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign); 388 sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign);
361 sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize); 389 sec->shdr.sh_entsize = elf_xword_to_cpu(shdr.sh_entsize);
362 if (sec->shdr.sh_link < ehdr.e_shnum) 390 if (sec->shdr.sh_link < ehdr.e_shnum)
363 sec->link = &secs[sec->shdr.sh_link]; 391 sec->link = &secs[sec->shdr.sh_link];
364 } 392 }
@@ -412,12 +440,12 @@ static void read_symtabs(FILE *fp)
412 die("Cannot read symbol table: %s\n", 440 die("Cannot read symbol table: %s\n",
413 strerror(errno)); 441 strerror(errno));
414 } 442 }
415 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { 443 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
416 Elf32_Sym *sym = &sec->symtab[j]; 444 Elf_Sym *sym = &sec->symtab[j];
417 sym->st_name = elf32_to_cpu(sym->st_name); 445 sym->st_name = elf_word_to_cpu(sym->st_name);
418 sym->st_value = elf32_to_cpu(sym->st_value); 446 sym->st_value = elf_addr_to_cpu(sym->st_value);
419 sym->st_size = elf32_to_cpu(sym->st_size); 447 sym->st_size = elf_xword_to_cpu(sym->st_size);
420 sym->st_shndx = elf16_to_cpu(sym->st_shndx); 448 sym->st_shndx = elf_half_to_cpu(sym->st_shndx);
421 } 449 }
422 } 450 }
423} 451}
@@ -428,7 +456,7 @@ static void read_relocs(FILE *fp)
428 int i,j; 456 int i,j;
429 for (i = 0; i < ehdr.e_shnum; i++) { 457 for (i = 0; i < ehdr.e_shnum; i++) {
430 struct section *sec = &secs[i]; 458 struct section *sec = &secs[i];
431 if (sec->shdr.sh_type != SHT_REL) { 459 if (sec->shdr.sh_type != SHT_REL_TYPE) {
432 continue; 460 continue;
433 } 461 }
434 sec->reltab = malloc(sec->shdr.sh_size); 462 sec->reltab = malloc(sec->shdr.sh_size);
@@ -445,10 +473,10 @@ static void read_relocs(FILE *fp)
445 die("Cannot read symbol table: %s\n", 473 die("Cannot read symbol table: %s\n",
446 strerror(errno)); 474 strerror(errno));
447 } 475 }
448 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { 476 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
449 Elf32_Rel *rel = &sec->reltab[j]; 477 Elf_Rel *rel = &sec->reltab[j];
450 rel->r_offset = elf32_to_cpu(rel->r_offset); 478 rel->r_offset = elf_addr_to_cpu(rel->r_offset);
451 rel->r_info = elf32_to_cpu(rel->r_info); 479 rel->r_info = elf_xword_to_cpu(rel->r_info);
452 } 480 }
453 } 481 }
454} 482}
@@ -468,8 +496,8 @@ static void print_absolute_symbols(void)
468 continue; 496 continue;
469 } 497 }
470 sym_strtab = sec->link->strtab; 498 sym_strtab = sec->link->strtab;
471 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { 499 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
472 Elf32_Sym *sym; 500 Elf_Sym *sym;
473 const char *name; 501 const char *name;
474 sym = &sec->symtab[j]; 502 sym = &sec->symtab[j];
475 name = sym_name(sym_strtab, sym); 503 name = sym_name(sym_strtab, sym);
@@ -478,9 +506,9 @@ static void print_absolute_symbols(void)
478 } 506 }
479 printf("%5d %08x %5d %10s %10s %12s %s\n", 507 printf("%5d %08x %5d %10s %10s %12s %s\n",
480 j, sym->st_value, sym->st_size, 508 j, sym->st_value, sym->st_size,
481 sym_type(ELF32_ST_TYPE(sym->st_info)), 509 sym_type(ELF_ST_TYPE(sym->st_info)),
482 sym_bind(ELF32_ST_BIND(sym->st_info)), 510 sym_bind(ELF_ST_BIND(sym->st_info)),
483 sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)), 511 sym_visibility(ELF_ST_VISIBILITY(sym->st_other)),
484 name); 512 name);
485 } 513 }
486 } 514 }
@@ -495,9 +523,9 @@ static void print_absolute_relocs(void)
495 struct section *sec = &secs[i]; 523 struct section *sec = &secs[i];
496 struct section *sec_applies, *sec_symtab; 524 struct section *sec_applies, *sec_symtab;
497 char *sym_strtab; 525 char *sym_strtab;
498 Elf32_Sym *sh_symtab; 526 Elf_Sym *sh_symtab;
499 int j; 527 int j;
500 if (sec->shdr.sh_type != SHT_REL) { 528 if (sec->shdr.sh_type != SHT_REL_TYPE) {
501 continue; 529 continue;
502 } 530 }
503 sec_symtab = sec->link; 531 sec_symtab = sec->link;
@@ -507,12 +535,12 @@ static void print_absolute_relocs(void)
507 } 535 }
508 sh_symtab = sec_symtab->symtab; 536 sh_symtab = sec_symtab->symtab;
509 sym_strtab = sec_symtab->link->strtab; 537 sym_strtab = sec_symtab->link->strtab;
510 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { 538 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
511 Elf32_Rel *rel; 539 Elf_Rel *rel;
512 Elf32_Sym *sym; 540 Elf_Sym *sym;
513 const char *name; 541 const char *name;
514 rel = &sec->reltab[j]; 542 rel = &sec->reltab[j];
515 sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; 543 sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
516 name = sym_name(sym_strtab, sym); 544 name = sym_name(sym_strtab, sym);
517 if (sym->st_shndx != SHN_ABS) { 545 if (sym->st_shndx != SHN_ABS) {
518 continue; 546 continue;
@@ -545,7 +573,7 @@ static void print_absolute_relocs(void)
545 printf("%08x %08x %10s %08x %s\n", 573 printf("%08x %08x %10s %08x %s\n",
546 rel->r_offset, 574 rel->r_offset,
547 rel->r_info, 575 rel->r_info,
548 rel_type(ELF32_R_TYPE(rel->r_info)), 576 rel_type(ELF_R_TYPE(rel->r_info)),
549 sym->st_value, 577 sym->st_value,
550 name); 578 name);
551 } 579 }
@@ -555,19 +583,19 @@ static void print_absolute_relocs(void)
555 printf("\n"); 583 printf("\n");
556} 584}
557 585
558static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), 586static void walk_relocs(void (*visit)(Elf_Rel *rel, Elf_Sym *sym),
559 int use_real_mode) 587 int use_real_mode)
560{ 588{
561 int i; 589 int i;
562 /* Walk through the relocations */ 590 /* Walk through the relocations */
563 for (i = 0; i < ehdr.e_shnum; i++) { 591 for (i = 0; i < ehdr.e_shnum; i++) {
564 char *sym_strtab; 592 char *sym_strtab;
565 Elf32_Sym *sh_symtab; 593 Elf_Sym *sh_symtab;
566 struct section *sec_applies, *sec_symtab; 594 struct section *sec_applies, *sec_symtab;
567 int j; 595 int j;
568 struct section *sec = &secs[i]; 596 struct section *sec = &secs[i];
569 597
570 if (sec->shdr.sh_type != SHT_REL) { 598 if (sec->shdr.sh_type != SHT_REL_TYPE) {
571 continue; 599 continue;
572 } 600 }
573 sec_symtab = sec->link; 601 sec_symtab = sec->link;
@@ -577,16 +605,16 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
577 } 605 }
578 sh_symtab = sec_symtab->symtab; 606 sh_symtab = sec_symtab->symtab;
579 sym_strtab = sec_symtab->link->strtab; 607 sym_strtab = sec_symtab->link->strtab;
580 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { 608 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
581 Elf32_Rel *rel; 609 Elf_Rel *rel;
582 Elf32_Sym *sym; 610 Elf_Sym *sym;
583 unsigned r_type; 611 unsigned r_type;
584 const char *symname; 612 const char *symname;
585 int shn_abs; 613 int shn_abs;
586 614
587 rel = &sec->reltab[j]; 615 rel = &sec->reltab[j];
588 sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; 616 sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
589 r_type = ELF32_R_TYPE(rel->r_info); 617 r_type = ELF_R_TYPE(rel->r_info);
590 618
591 shn_abs = sym->st_shndx == SHN_ABS; 619 shn_abs = sym->st_shndx == SHN_ABS;
592 620
@@ -647,18 +675,18 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
647 } 675 }
648} 676}
649 677
650static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) 678static void count_reloc(Elf_Rel *rel, Elf_Sym *sym)
651{ 679{
652 if (ELF32_R_TYPE(rel->r_info) == R_386_16) 680 if (ELF_R_TYPE(rel->r_info) == R_386_16)
653 reloc16_count++; 681 reloc16_count++;
654 else 682 else
655 reloc_count++; 683 reloc_count++;
656} 684}
657 685
658static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) 686static void collect_reloc(Elf_Rel *rel, Elf_Sym *sym)
659{ 687{
660 /* Remember the address that needs to be adjusted. */ 688 /* Remember the address that needs to be adjusted. */
661 if (ELF32_R_TYPE(rel->r_info) == R_386_16) 689 if (ELF_R_TYPE(rel->r_info) == R_386_16)
662 relocs16[reloc16_idx++] = rel->r_offset; 690 relocs16[reloc16_idx++] = rel->r_offset;
663 else 691 else
664 relocs[reloc_idx++] = rel->r_offset; 692 relocs[reloc_idx++] = rel->r_offset;