Skip to content

Commit ae4ac12

Browse files
atsushi-nemotosravnborg
authored andcommitted
kbuild: make better section mismatch reports on i386 and mips
On i386 and MIPS, warn_sec_mismatch() sometimes fails to show usefull symbol name. This is because empty 'refsym' due to 0 r_addend value. This patch is to adjust r_addend value, consulting with apply_relocate() routine in kernel code. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
1 parent b70e325 commit ae4ac12

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

scripts/mod/modpost.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
374374
hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
375375
hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
376376
hdr->e_machine = TO_NATIVE(hdr->e_machine);
377+
hdr->e_type = TO_NATIVE(hdr->e_type);
377378
sechdrs = (void *)hdr + hdr->e_shoff;
378379
info->sechdrs = sechdrs;
379380

@@ -384,6 +385,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
384385
sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
385386
sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
386387
sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
388+
sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
389+
sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
387390
}
388391
/* Find symbol table. */
389392
for (i = 1; i < hdr->e_shnum; i++) {
@@ -753,6 +756,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
753756
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
754757
if (sym->st_shndx != relsym->st_shndx)
755758
continue;
759+
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
760+
continue;
756761
if (sym->st_value == addr)
757762
return sym;
758763
}
@@ -895,6 +900,58 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
895900
}
896901
}
897902

903+
static unsigned int *reloc_location(struct elf_info *elf,
904+
int rsection, Elf_Rela *r)
905+
{
906+
Elf_Shdr *sechdrs = elf->sechdrs;
907+
int section = sechdrs[rsection].sh_info;
908+
909+
return (void *)elf->hdr + sechdrs[section].sh_offset +
910+
(r->r_offset - sechdrs[section].sh_addr);
911+
}
912+
913+
static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
914+
{
915+
unsigned int r_typ = ELF_R_TYPE(r->r_info);
916+
unsigned int *location = reloc_location(elf, rsection, r);
917+
918+
switch (r_typ) {
919+
case R_386_32:
920+
r->r_addend = TO_NATIVE(*location);
921+
break;
922+
case R_386_PC32:
923+
r->r_addend = TO_NATIVE(*location) + 4;
924+
/* For CONFIG_RELOCATABLE=y */
925+
if (elf->hdr->e_type == ET_EXEC)
926+
r->r_addend += r->r_offset;
927+
break;
928+
}
929+
return 0;
930+
}
931+
932+
static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
933+
{
934+
unsigned int r_typ = ELF_R_TYPE(r->r_info);
935+
unsigned int *location = reloc_location(elf, rsection, r);
936+
unsigned int inst;
937+
938+
if (r_typ == R_MIPS_HI16)
939+
return 1; /* skip this */
940+
inst = TO_NATIVE(*location);
941+
switch (r_typ) {
942+
case R_MIPS_LO16:
943+
r->r_addend = inst & 0xffff;
944+
break;
945+
case R_MIPS_26:
946+
r->r_addend = (inst & 0x03ffffff) << 2;
947+
break;
948+
case R_MIPS_32:
949+
r->r_addend = inst;
950+
break;
951+
}
952+
return 0;
953+
}
954+
898955
/**
899956
* A module includes a number of sections that are discarded
900957
* either when loaded or when used as built-in.
@@ -938,8 +995,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
938995
r.r_offset = TO_NATIVE(rela->r_offset);
939996
#if KERNEL_ELFCLASS == ELFCLASS64
940997
if (hdr->e_machine == EM_MIPS) {
998+
unsigned int r_typ;
941999
r_sym = ELF64_MIPS_R_SYM(rela->r_info);
9421000
r_sym = TO_NATIVE(r_sym);
1001+
r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
1002+
r.r_info = ELF64_R_INFO(r_sym, r_typ);
9431003
} else {
9441004
r.r_info = TO_NATIVE(rela->r_info);
9451005
r_sym = ELF_R_SYM(r.r_info);
@@ -972,8 +1032,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
9721032
r.r_offset = TO_NATIVE(rel->r_offset);
9731033
#if KERNEL_ELFCLASS == ELFCLASS64
9741034
if (hdr->e_machine == EM_MIPS) {
1035+
unsigned int r_typ;
9751036
r_sym = ELF64_MIPS_R_SYM(rel->r_info);
9761037
r_sym = TO_NATIVE(r_sym);
1038+
r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
1039+
r.r_info = ELF64_R_INFO(r_sym, r_typ);
9771040
} else {
9781041
r.r_info = TO_NATIVE(rel->r_info);
9791042
r_sym = ELF_R_SYM(r.r_info);
@@ -983,6 +1046,16 @@ static void check_sec_ref(struct module *mod, const char *modname,
9831046
r_sym = ELF_R_SYM(r.r_info);
9841047
#endif
9851048
r.r_addend = 0;
1049+
switch (hdr->e_machine) {
1050+
case EM_386:
1051+
if (addend_386_rel(elf, i, &r))
1052+
continue;
1053+
break;
1054+
case EM_MIPS:
1055+
if (addend_mips_rel(elf, i, &r))
1056+
continue;
1057+
break;
1058+
}
9861059
sym = elf->symtab_start + r_sym;
9871060
/* Skip special sections */
9881061
if (sym->st_shndx >= SHN_LORESERVE)

scripts/mod/modpost.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ typedef union
6060
#define ELF64_MIPS_R_SYM(i) \
6161
((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym)
6262

63+
#define ELF64_MIPS_R_TYPE(i) \
64+
((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1)
65+
6366
#if KERNEL_ELFDATA != HOST_ELFDATA
6467

6568
static inline void __endian(const void *src, void *dest, unsigned int size)

0 commit comments

Comments
 (0)