diff options
| author | Sam Ravnborg <sam@ravnborg.org> | 2008-01-18 15:49:29 -0500 |
|---|---|---|
| committer | Sam Ravnborg <sam@ravnborg.org> | 2008-01-28 17:14:40 -0500 |
| commit | 5b24c0715fc4c71e60e9a684248cc49d62dfa900 (patch) | |
| tree | d463896713b538ac9cf5ce637a9ee9d54d952055 /scripts/mod | |
| parent | 9ad21c3f3ecffeb56be7b35030d7ec2f30b6fe11 (diff) | |
kbuild: code refactoring in modpost
Split a too long function up in smaller bits to make
prgram logic easier to follow.
A few related changes done due to parameter
changes.
No functional changes.
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/modpost.c | 242 |
1 files changed, 137 insertions, 105 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 902ee55f327..e4630135979 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -937,19 +937,19 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
| 937 | } | 937 | } |
| 938 | 938 | ||
| 939 | static unsigned int *reloc_location(struct elf_info *elf, | 939 | static unsigned int *reloc_location(struct elf_info *elf, |
| 940 | int rsection, Elf_Rela *r) | 940 | Elf_Shdr *sechdr, Elf_Rela *r) |
| 941 | { | 941 | { |
| 942 | Elf_Shdr *sechdrs = elf->sechdrs; | 942 | Elf_Shdr *sechdrs = elf->sechdrs; |
| 943 | int section = sechdrs[rsection].sh_info; | 943 | int section = sechdr->sh_info; |
| 944 | 944 | ||
| 945 | return (void *)elf->hdr + sechdrs[section].sh_offset + | 945 | return (void *)elf->hdr + sechdrs[section].sh_offset + |
| 946 | (r->r_offset - sechdrs[section].sh_addr); | 946 | (r->r_offset - sechdrs[section].sh_addr); |
| 947 | } | 947 | } |
| 948 | 948 | ||
| 949 | static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | 949 | static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
| 950 | { | 950 | { |
| 951 | unsigned int r_typ = ELF_R_TYPE(r->r_info); | 951 | unsigned int r_typ = ELF_R_TYPE(r->r_info); |
| 952 | unsigned int *location = reloc_location(elf, rsection, r); | 952 | unsigned int *location = reloc_location(elf, sechdr, r); |
| 953 | 953 | ||
| 954 | switch (r_typ) { | 954 | switch (r_typ) { |
| 955 | case R_386_32: | 955 | case R_386_32: |
| @@ -965,7 +965,7 @@ static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
| 965 | return 0; | 965 | return 0; |
| 966 | } | 966 | } |
| 967 | 967 | ||
| 968 | static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | 968 | static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
| 969 | { | 969 | { |
| 970 | unsigned int r_typ = ELF_R_TYPE(r->r_info); | 970 | unsigned int r_typ = ELF_R_TYPE(r->r_info); |
| 971 | 971 | ||
| @@ -978,8 +978,8 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
| 978 | case R_ARM_PC24: | 978 | case R_ARM_PC24: |
| 979 | /* From ARM ABI: ((S + A) | T) - P */ | 979 | /* From ARM ABI: ((S + A) | T) - P */ |
| 980 | r->r_addend = (int)(long)(elf->hdr + | 980 | r->r_addend = (int)(long)(elf->hdr + |
| 981 | elf->sechdrs[rsection].sh_offset + | 981 | sechdr->sh_offset + |
| 982 | (r->r_offset - elf->sechdrs[rsection].sh_addr)); | 982 | (r->r_offset - sechdr->sh_addr)); |
| 983 | break; | 983 | break; |
| 984 | default: | 984 | default: |
| 985 | return 1; | 985 | return 1; |
| @@ -987,10 +987,10 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
| 987 | return 0; | 987 | return 0; |
| 988 | } | 988 | } |
| 989 | 989 | ||
| 990 | static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | 990 | static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
| 991 | { | 991 | { |
| 992 | unsigned int r_typ = ELF_R_TYPE(r->r_info); | 992 | unsigned int r_typ = ELF_R_TYPE(r->r_info); |
| 993 | unsigned int *location = reloc_location(elf, rsection, r); | 993 | unsigned int *location = reloc_location(elf, sechdr, r); |
| 994 | unsigned int inst; | 994 | unsigned int inst; |
| 995 | 995 | ||
| 996 | if (r_typ == R_MIPS_HI16) | 996 | if (r_typ == R_MIPS_HI16) |
| @@ -1010,6 +1010,128 @@ static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
| 1010 | return 0; | 1010 | return 0; |
| 1011 | } | 1011 | } |
| 1012 | 1012 | ||
| 1013 | static void section_rela(const char *modname, struct elf_info *elf, | ||
| 1014 | Elf_Shdr *sechdr, int section(const char *), | ||
| 1015 | int section_ref_ok(const char *)) | ||
| 1016 | { | ||
| 1017 | Elf_Sym *sym; | ||
| 1018 | Elf_Rela *rela; | ||
| 1019 | Elf_Rela r; | ||
| 1020 | unsigned int r_sym; | ||
| 1021 | const char *fromsec; | ||
| 1022 | const char * tosec; | ||
| 1023 | |||
| 1024 | Elf_Ehdr *hdr = elf->hdr; | ||
| 1025 | Elf_Rela *start = (void *)hdr + sechdr->sh_offset; | ||
| 1026 | Elf_Rela *stop = (void *)start + sechdr->sh_size; | ||
| 1027 | |||
| 1028 | const char *secstrings = (void *)hdr + | ||
| 1029 | elf->sechdrs[hdr->e_shstrndx].sh_offset; | ||
| 1030 | |||
| 1031 | fromsec = secstrings + sechdr->sh_name; | ||
| 1032 | fromsec += strlen(".rela"); | ||
| 1033 | /* if from section (name) is know good then skip it */ | ||
| 1034 | if (section_ref_ok(fromsec)) | ||
| 1035 | return; | ||
| 1036 | |||
| 1037 | for (rela = start; rela < stop; rela++) { | ||
| 1038 | r.r_offset = TO_NATIVE(rela->r_offset); | ||
| 1039 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
| 1040 | if (hdr->e_machine == EM_MIPS) { | ||
| 1041 | unsigned int r_typ; | ||
| 1042 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); | ||
| 1043 | r_sym = TO_NATIVE(r_sym); | ||
| 1044 | r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | ||
| 1045 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
| 1046 | } else { | ||
| 1047 | r.r_info = TO_NATIVE(rela->r_info); | ||
| 1048 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1049 | } | ||
| 1050 | #else | ||
| 1051 | r.r_info = TO_NATIVE(rela->r_info); | ||
| 1052 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1053 | #endif | ||
| 1054 | r.r_addend = TO_NATIVE(rela->r_addend); | ||
| 1055 | sym = elf->symtab_start + r_sym; | ||
| 1056 | /* Skip special sections */ | ||
| 1057 | if (sym->st_shndx >= SHN_LORESERVE) | ||
| 1058 | continue; | ||
| 1059 | |||
| 1060 | tosec = secstrings + | ||
| 1061 | elf->sechdrs[sym->st_shndx].sh_name; | ||
| 1062 | if (section(tosec)) | ||
| 1063 | warn_sec_mismatch(modname, fromsec, elf, sym, r); | ||
| 1064 | } | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static void section_rel(const char *modname, struct elf_info *elf, | ||
| 1068 | Elf_Shdr *sechdr, int section(const char *), | ||
| 1069 | int section_ref_ok(const char *)) | ||
| 1070 | { | ||
| 1071 | Elf_Sym *sym; | ||
| 1072 | Elf_Rel *rel; | ||
| 1073 | Elf_Rela r; | ||
| 1074 | unsigned int r_sym; | ||
| 1075 | const char *fromsec; | ||
| 1076 | const char * tosec; | ||
| 1077 | |||
| 1078 | Elf_Ehdr *hdr = elf->hdr; | ||
| 1079 | Elf_Rel *start = (void *)hdr + sechdr->sh_offset; | ||
| 1080 | Elf_Rel *stop = (void *)start + sechdr->sh_size; | ||
| 1081 | |||
| 1082 | const char *secstrings = (void *)hdr + | ||
| 1083 | elf->sechdrs[hdr->e_shstrndx].sh_offset; | ||
| 1084 | |||
| 1085 | fromsec = secstrings + sechdr->sh_name; | ||
| 1086 | fromsec += strlen(".rel"); | ||
| 1087 | /* if from section (name) is know good then skip it */ | ||
| 1088 | if (section_ref_ok(fromsec)) | ||
| 1089 | return; | ||
| 1090 | |||
| 1091 | for (rel = start; rel < stop; rel++) { | ||
| 1092 | r.r_offset = TO_NATIVE(rel->r_offset); | ||
| 1093 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
| 1094 | if (hdr->e_machine == EM_MIPS) { | ||
| 1095 | unsigned int r_typ; | ||
| 1096 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); | ||
| 1097 | r_sym = TO_NATIVE(r_sym); | ||
| 1098 | r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | ||
| 1099 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
| 1100 | } else { | ||
| 1101 | r.r_info = TO_NATIVE(rel->r_info); | ||
| 1102 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1103 | } | ||
| 1104 | #else | ||
| 1105 | r.r_info = TO_NATIVE(rel->r_info); | ||
| 1106 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1107 | #endif | ||
| 1108 | r.r_addend = 0; | ||
| 1109 | switch (hdr->e_machine) { | ||
| 1110 | case EM_386: | ||
| 1111 | if (addend_386_rel(elf, sechdr, &r)) | ||
| 1112 | continue; | ||
| 1113 | break; | ||
| 1114 | case EM_ARM: | ||
| 1115 | if (addend_arm_rel(elf, sechdr, &r)) | ||
| 1116 | continue; | ||
| 1117 | break; | ||
| 1118 | case EM_MIPS: | ||
| 1119 | if (addend_mips_rel(elf, sechdr, &r)) | ||
| 1120 | continue; | ||
| 1121 | break; | ||
| 1122 | } | ||
| 1123 | sym = elf->symtab_start + r_sym; | ||
| 1124 | /* Skip special sections */ | ||
| 1125 | if (sym->st_shndx >= SHN_LORESERVE) | ||
| 1126 | continue; | ||
| 1127 | |||
| 1128 | tosec = secstrings + | ||
| 1129 | elf->sechdrs[sym->st_shndx].sh_name; | ||
| 1130 | if (section(tosec)) | ||
| 1131 | warn_sec_mismatch(modname, fromsec, elf, sym, r); | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | |||
| 1013 | /** | 1135 | /** |
| 1014 | * A module includes a number of sections that are discarded | 1136 | * A module includes a number of sections that are discarded |
| 1015 | * either when loaded or when used as built-in. | 1137 | * either when loaded or when used as built-in. |
| @@ -1028,108 +1150,18 @@ static void check_sec_ref(struct module *mod, const char *modname, | |||
| 1028 | int section_ref_ok(const char *)) | 1150 | int section_ref_ok(const char *)) |
| 1029 | { | 1151 | { |
| 1030 | int i; | 1152 | int i; |
| 1031 | Elf_Sym *sym; | ||
| 1032 | Elf_Ehdr *hdr = elf->hdr; | 1153 | Elf_Ehdr *hdr = elf->hdr; |
| 1033 | Elf_Shdr *sechdrs = elf->sechdrs; | 1154 | Elf_Shdr *sechdrs = elf->sechdrs; |
| 1034 | const char *secstrings = (void *)hdr + | ||
| 1035 | sechdrs[hdr->e_shstrndx].sh_offset; | ||
| 1036 | 1155 | ||
| 1037 | /* Walk through all sections */ | 1156 | /* Walk through all sections */ |
| 1038 | for (i = 0; i < hdr->e_shnum; i++) { | 1157 | for (i = 0; i < hdr->e_shnum; i++) { |
| 1039 | const char *name = secstrings + sechdrs[i].sh_name; | ||
| 1040 | const char *secname; | ||
| 1041 | Elf_Rela r; | ||
| 1042 | unsigned int r_sym; | ||
| 1043 | /* We want to process only relocation sections and not .init */ | 1158 | /* We want to process only relocation sections and not .init */ |
| 1044 | if (sechdrs[i].sh_type == SHT_RELA) { | 1159 | if (sechdrs[i].sh_type == SHT_RELA) |
| 1045 | Elf_Rela *rela; | 1160 | section_rela(modname, elf, &elf->sechdrs[i], |
| 1046 | Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; | 1161 | section, section_ref_ok); |
| 1047 | Elf_Rela *stop = (void *)start + sechdrs[i].sh_size; | 1162 | else if (sechdrs[i].sh_type == SHT_REL) |
| 1048 | name += strlen(".rela"); | 1163 | section_rel(modname, elf, &elf->sechdrs[i], |
| 1049 | if (section_ref_ok(name)) | 1164 | section, section_ref_ok); |
| 1050 | continue; | ||
| 1051 | |||
| 1052 | for (rela = start; rela < stop; rela++) { | ||
| 1053 | r.r_offset = TO_NATIVE(rela->r_offset); | ||
| 1054 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
| 1055 | if (hdr->e_machine == EM_MIPS) { | ||
| 1056 | unsigned int r_typ; | ||
| 1057 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); | ||
| 1058 | r_sym = TO_NATIVE(r_sym); | ||
| 1059 | r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | ||
| 1060 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
| 1061 | } else { | ||
| 1062 | r.r_info = TO_NATIVE(rela->r_info); | ||
| 1063 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1064 | } | ||
| 1065 | #else | ||
| 1066 | r.r_info = TO_NATIVE(rela->r_info); | ||
| 1067 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1068 | #endif | ||
| 1069 | r.r_addend = TO_NATIVE(rela->r_addend); | ||
| 1070 | sym = elf->symtab_start + r_sym; | ||
| 1071 | /* Skip special sections */ | ||
| 1072 | if (sym->st_shndx >= SHN_LORESERVE) | ||
| 1073 | continue; | ||
| 1074 | |||
| 1075 | secname = secstrings + | ||
| 1076 | sechdrs[sym->st_shndx].sh_name; | ||
| 1077 | if (section(secname)) | ||
| 1078 | warn_sec_mismatch(modname, name, | ||
| 1079 | elf, sym, r); | ||
| 1080 | } | ||
| 1081 | } else if (sechdrs[i].sh_type == SHT_REL) { | ||
| 1082 | Elf_Rel *rel; | ||
| 1083 | Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset; | ||
| 1084 | Elf_Rel *stop = (void *)start + sechdrs[i].sh_size; | ||
| 1085 | name += strlen(".rel"); | ||
| 1086 | if (section_ref_ok(name)) | ||
| 1087 | continue; | ||
| 1088 | |||
| 1089 | for (rel = start; rel < stop; rel++) { | ||
| 1090 | r.r_offset = TO_NATIVE(rel->r_offset); | ||
| 1091 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
| 1092 | if (hdr->e_machine == EM_MIPS) { | ||
| 1093 | unsigned int r_typ; | ||
| 1094 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); | ||
| 1095 | r_sym = TO_NATIVE(r_sym); | ||
| 1096 | r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | ||
| 1097 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
| 1098 | } else { | ||
| 1099 | r.r_info = TO_NATIVE(rel->r_info); | ||
| 1100 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1101 | } | ||
| 1102 | #else | ||
| 1103 | r.r_info = TO_NATIVE(rel->r_info); | ||
| 1104 | r_sym = ELF_R_SYM(r.r_info); | ||
| 1105 | #endif | ||
| 1106 | r.r_addend = 0; | ||
| 1107 | switch (hdr->e_machine) { | ||
| 1108 | case EM_386: | ||
| 1109 | if (addend_386_rel(elf, i, &r)) | ||
| 1110 | continue; | ||
| 1111 | break; | ||
| 1112 | case EM_ARM: | ||
| 1113 | if (addend_arm_rel(elf, i, &r)) | ||
| 1114 | continue; | ||
| 1115 | break; | ||
| 1116 | case EM_MIPS: | ||
| 1117 | if (addend_mips_rel(elf, i, &r)) | ||
| 1118 | continue; | ||
| 1119 | break; | ||
| 1120 | } | ||
| 1121 | sym = elf->symtab_start + r_sym; | ||
| 1122 | /* Skip special sections */ | ||
| 1123 | if (sym->st_shndx >= SHN_LORESERVE) | ||
| 1124 | continue; | ||
| 1125 | |||
| 1126 | secname = secstrings + | ||
| 1127 | sechdrs[sym->st_shndx].sh_name; | ||
| 1128 | if (section(secname)) | ||
| 1129 | warn_sec_mismatch(modname, name, | ||
| 1130 | elf, sym, r); | ||
| 1131 | } | ||
| 1132 | } | ||
| 1133 | } | 1165 | } |
| 1134 | } | 1166 | } |
| 1135 | 1167 | ||
