link_elf.c (73624a804a52723d7377003bfee94af39e9fa1fe) | link_elf.c (36716fe2e6eddac7ab1b9e9b1a268885a3985932) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1998-2000 Doug Rabson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 174 unchanged lines hidden (view full) --- 183#if ELF_TARG_CLASS == ELFCLASS32 184 "elf32", 185#else 186 "elf64", 187#endif 188 link_elf_methods, sizeof(struct elf_file) 189}; 190 | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1998-2000 Doug Rabson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 174 unchanged lines hidden (view full) --- 183#if ELF_TARG_CLASS == ELFCLASS32 184 "elf32", 185#else 186 "elf64", 187#endif 188 link_elf_methods, sizeof(struct elf_file) 189}; 190 |
191typedef int (*elf_reloc_fn)(linker_file_t lf, Elf_Addr relocbase, 192 const void *data, int type, elf_lookup_fn lookup); 193 |
|
191static int parse_dynamic(elf_file_t); 192static int relocate_file(elf_file_t); | 194static int parse_dynamic(elf_file_t); 195static int relocate_file(elf_file_t); |
193static int relocate_file1(elf_file_t ef, int (*elf_reloc_func)( 194 linker_file_t lf, Elf_Addr relocbase, const void *data, 195 int type, elf_lookup_fn lookup)); | 196static int relocate_file1(elf_file_t ef, elf_lookup_fn lookup, 197 elf_reloc_fn reloc, bool ifuncs); |
196static int link_elf_preload_parse_symbols(elf_file_t); 197 198static struct elf_set_head set_pcpu_list; 199#ifdef VIMAGE 200static struct elf_set_head set_vnet_list; 201#endif 202 203static void --- 976 unchanged lines hidden (view full) --- 1180 if (ELF_R_SYM(r_info)) { 1181 ref = ef->symtab + ELF_R_SYM(r_info); 1182 return (ef->strtab + ref->st_name); 1183 } 1184 return (NULL); 1185} 1186 1187static int | 198static int link_elf_preload_parse_symbols(elf_file_t); 199 200static struct elf_set_head set_pcpu_list; 201#ifdef VIMAGE 202static struct elf_set_head set_vnet_list; 203#endif 204 205static void --- 976 unchanged lines hidden (view full) --- 1182 if (ELF_R_SYM(r_info)) { 1183 ref = ef->symtab + ELF_R_SYM(r_info); 1184 return (ef->strtab + ref->st_name); 1185 } 1186 return (NULL); 1187} 1188 1189static int |
1188relocate_file1(elf_file_t ef, int (*elf_reloc_func)(linker_file_t lf, 1189 Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup)) | 1190symbol_type(elf_file_t ef, Elf_Size r_info) |
1190{ | 1191{ |
1191 const Elf_Rel *rellim; | 1192 const Elf_Sym *ref; 1193 1194 if (ELF_R_SYM(r_info)) { 1195 ref = ef->symtab + ELF_R_SYM(r_info); 1196 return (ELF_ST_TYPE(ref->st_info)); 1197 } 1198 return (STT_NOTYPE); 1199} 1200 1201static int 1202relocate_file1(elf_file_t ef, elf_lookup_fn lookup, elf_reloc_fn reloc, 1203 bool ifuncs) 1204{ |
1192 const Elf_Rel *rel; | 1205 const Elf_Rel *rel; |
1193 const Elf_Rela *relalim; | |
1194 const Elf_Rela *rela; 1195 const char *symname; 1196 | 1206 const Elf_Rela *rela; 1207 const char *symname; 1208 |
1197 /* Perform relocations without addend if there are any: */ 1198 rel = ef->rel; 1199 if (rel != NULL) { 1200 rellim = (const Elf_Rel *) 1201 ((const char *)ef->rel + ef->relsize); 1202 while (rel < rellim) { 1203 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rel, 1204 ELF_RELOC_REL, elf_lookup)) { 1205 symname = symbol_name(ef, rel->r_info); 1206 printf("link_elf: symbol %s undefined\n", symname); 1207 return (ENOENT); 1208 } 1209 rel++; 1210 } 1211 } | 1209#define APPLY_RELOCS(iter, tbl, tblsize, type) do { \ 1210 for ((iter) = (tbl); (iter) != NULL && \ 1211 (iter) < (tbl) + (tblsize) / sizeof(*(iter)); (iter)++) { \ 1212 if ((symbol_type(ef, (iter)->r_info) == \ 1213 STT_GNU_IFUNC || \ 1214 elf_is_ifunc_reloc((iter)->r_info)) != ifuncs) \ 1215 continue; \ 1216 if (reloc(&ef->lf, (Elf_Addr)ef->address, \ 1217 (iter), (type), lookup)) { \ 1218 symname = symbol_name(ef, (iter)->r_info); \ 1219 printf("link_elf: symbol %s undefined\n", \ 1220 symname); \ 1221 return (ENOENT); \ 1222 } \ 1223 } \ 1224} while (0) |
1212 | 1225 |
1213 /* Perform relocations with addend if there are any: */ 1214 rela = ef->rela; 1215 if (rela != NULL) { 1216 relalim = (const Elf_Rela *) 1217 ((const char *)ef->rela + ef->relasize); 1218 while (rela < relalim) { 1219 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rela, 1220 ELF_RELOC_RELA, elf_lookup)) { 1221 symname = symbol_name(ef, rela->r_info); 1222 printf("link_elf: symbol %s undefined\n", 1223 symname); 1224 return (ENOENT); 1225 } 1226 rela++; 1227 } 1228 } | 1226 APPLY_RELOCS(rel, ef->rel, ef->relsize, ELF_RELOC_REL); 1227 APPLY_RELOCS(rela, ef->rela, ef->relasize, ELF_RELOC_RELA); 1228 APPLY_RELOCS(rel, ef->pltrel, ef->pltrelsize, ELF_RELOC_REL); 1229 APPLY_RELOCS(rela, ef->pltrela, ef->pltrelasize, ELF_RELOC_RELA); |
1229 | 1230 |
1230 /* Perform PLT relocations without addend if there are any: */ 1231 rel = ef->pltrel; 1232 if (rel != NULL) { 1233 rellim = (const Elf_Rel *) 1234 ((const char *)ef->pltrel + ef->pltrelsize); 1235 while (rel < rellim) { 1236 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rel, 1237 ELF_RELOC_REL, elf_lookup)) { 1238 symname = symbol_name(ef, rel->r_info); 1239 printf("link_elf: symbol %s undefined\n", 1240 symname); 1241 return (ENOENT); 1242 } 1243 rel++; 1244 } 1245 } | 1231#undef APPLY_RELOCS |
1246 | 1232 |
1247 /* Perform relocations with addend if there are any: */ 1248 rela = ef->pltrela; 1249 if (rela != NULL) { 1250 relalim = (const Elf_Rela *) 1251 ((const char *)ef->pltrela + ef->pltrelasize); 1252 while (rela < relalim) { 1253 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rela, 1254 ELF_RELOC_RELA, elf_lookup)) { 1255 symname = symbol_name(ef, rela->r_info); 1256 printf("link_elf: symbol %s undefined\n", 1257 symname); 1258 return (ENOENT); 1259 } 1260 rela++; 1261 } 1262 } 1263 | |
1264 return (0); 1265} 1266 1267static int 1268relocate_file(elf_file_t ef) 1269{ | 1233 return (0); 1234} 1235 1236static int 1237relocate_file(elf_file_t ef) 1238{ |
1270 int e; | 1239 int error; |
1271 | 1240 |
1272 e = relocate_file1(ef, elf_reloc); 1273#if defined(__i386__) || defined(__amd64__) 1274 if (e == 0) 1275 e = relocate_file1(ef, elf_reloc_ifunc); 1276#endif 1277 return (e); | 1241 error = relocate_file1(ef, elf_lookup, elf_reloc, false); 1242 if (error == 0) 1243 error = relocate_file1(ef, elf_lookup, elf_reloc, true); 1244 return (error); |
1278} 1279 1280/* 1281 * Hash function for symbol table lookup. Don't even think about changing 1282 * this. It is specified by the System V ABI. 1283 */ 1284static unsigned long 1285elf_hash(const char *name) --- 7 unchanged lines hidden (view full) --- 1293 if ((g = h & 0xf0000000) != 0) 1294 h ^= g >> 24; 1295 h &= ~g; 1296 } 1297 return (h); 1298} 1299 1300static int | 1245} 1246 1247/* 1248 * Hash function for symbol table lookup. Don't even think about changing 1249 * this. It is specified by the System V ABI. 1250 */ 1251static unsigned long 1252elf_hash(const char *name) --- 7 unchanged lines hidden (view full) --- 1260 if ((g = h & 0xf0000000) != 0) 1261 h ^= g >> 24; 1262 h &= ~g; 1263 } 1264 return (h); 1265} 1266 1267static int |
1301link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym) | 1268link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym) |
1302{ 1303 elf_file_t ef = (elf_file_t) lf; 1304 unsigned long symnum; 1305 const Elf_Sym* symp; 1306 const char *strp; 1307 unsigned long hash; 1308 int i; 1309 --- 372 unchanged lines hidden (view full) --- 1682 1683 if (*strtab == NULL) 1684 return (0); 1685 1686 return (ef->ddbstrcnt); 1687} 1688 1689#if defined(__i386__) || defined(__amd64__) | 1269{ 1270 elf_file_t ef = (elf_file_t) lf; 1271 unsigned long symnum; 1272 const Elf_Sym* symp; 1273 const char *strp; 1274 unsigned long hash; 1275 int i; 1276 --- 372 unchanged lines hidden (view full) --- 1649 1650 if (*strtab == NULL) 1651 return (0); 1652 1653 return (ef->ddbstrcnt); 1654} 1655 1656#if defined(__i386__) || defined(__amd64__) |
1657/* 1658 * Use this lookup routine when performing relocations early during boot. 1659 * The generic lookup routine depends on kobj, which is not initialized 1660 * at that point. 1661 */ 1662static int 1663elf_lookup_ifunc(linker_file_t lf, Elf_Size symidx, int deps __unused, 1664 Elf_Addr *res) 1665{ 1666 elf_file_t ef; 1667 const Elf_Sym *symp; 1668 caddr_t val; 1669 1670 ef = (elf_file_t)lf; 1671 symp = ef->symtab + symidx; 1672 if (ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC) { 1673 val = (caddr_t)ef->address + symp->st_value; 1674 *res = ((Elf_Addr (*)(void))val)(); 1675 return (0); 1676 } 1677 return (ENOENT); 1678} 1679 |
|
1690void 1691link_elf_ireloc(caddr_t kmdp) 1692{ 1693 struct elf_file eff; 1694 elf_file_t ef; 1695 volatile char *c; 1696 size_t i; 1697 | 1680void 1681link_elf_ireloc(caddr_t kmdp) 1682{ 1683 struct elf_file eff; 1684 elf_file_t ef; 1685 volatile char *c; 1686 size_t i; 1687 |
1698 ef = &eff; | 1688 ef = &eff; |
1699 1700 /* Do not use bzero/memset before ireloc is done. */ 1701 for (c = (char *)ef, i = 0; i < sizeof(*ef); i++) 1702 c[i] = 0; 1703 1704 ef->modptr = kmdp; 1705 ef->dynamic = (Elf_Dyn *)&_DYNAMIC; 1706 parse_dynamic(ef); 1707 ef->address = 0; 1708 link_elf_preload_parse_symbols(ef); | 1689 1690 /* Do not use bzero/memset before ireloc is done. */ 1691 for (c = (char *)ef, i = 0; i < sizeof(*ef); i++) 1692 c[i] = 0; 1693 1694 ef->modptr = kmdp; 1695 ef->dynamic = (Elf_Dyn *)&_DYNAMIC; 1696 parse_dynamic(ef); 1697 ef->address = 0; 1698 link_elf_preload_parse_symbols(ef); |
1709 relocate_file1(ef, elf_reloc_ifunc); | 1699 relocate_file1(ef, elf_lookup_ifunc, elf_reloc, true); |
1710} 1711#endif | 1700} 1701#endif |