link_elf.c (ee900504cf6496ff421d8f1ff73de9550f11ed8f) | link_elf.c (7035cf14ee3b658181facc80b72179e06a9a4f35) |
---|---|
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 --- 176 unchanged lines hidden (view full) --- 185#else 186 "elf64", 187#endif 188 link_elf_methods, sizeof(struct elf_file) 189}; 190 191static int parse_dynamic(elf_file_t); 192static int relocate_file(elf_file_t); | 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 --- 176 unchanged lines hidden (view full) --- 185#else 186 "elf64", 187#endif 188 link_elf_methods, sizeof(struct elf_file) 189}; 190 191static int parse_dynamic(elf_file_t); 192static 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)); |
|
193static int link_elf_preload_parse_symbols(elf_file_t); 194 195static struct elf_set_head set_pcpu_list; 196#ifdef VIMAGE 197static struct elf_set_head set_vnet_list; 198#endif 199 200static void --- 976 unchanged lines hidden (view full) --- 1177 if (ELF_R_SYM(r_info)) { 1178 ref = ef->symtab + ELF_R_SYM(r_info); 1179 return (ef->strtab + ref->st_name); 1180 } 1181 return (NULL); 1182} 1183 1184static int | 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 |
1185relocate_file(elf_file_t ef) | 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)) |
1186{ 1187 const Elf_Rel *rellim; 1188 const Elf_Rel *rel; 1189 const Elf_Rela *relalim; 1190 const Elf_Rela *rela; 1191 const char *symname; 1192 1193 /* Perform relocations without addend if there are any: */ 1194 rel = ef->rel; 1195 if (rel != NULL) { 1196 rellim = (const Elf_Rel *) 1197 ((const char *)ef->rel + ef->relsize); 1198 while (rel < rellim) { | 1190{ 1191 const Elf_Rel *rellim; 1192 const Elf_Rel *rel; 1193 const Elf_Rela *relalim; 1194 const Elf_Rela *rela; 1195 const char *symname; 1196 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) { |
1199 if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, | 1203 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rel, |
1200 ELF_RELOC_REL, elf_lookup)) { 1201 symname = symbol_name(ef, rel->r_info); 1202 printf("link_elf: symbol %s undefined\n", symname); 1203 return (ENOENT); 1204 } 1205 rel++; 1206 } 1207 } 1208 1209 /* Perform relocations with addend if there are any: */ 1210 rela = ef->rela; 1211 if (rela != NULL) { 1212 relalim = (const Elf_Rela *) 1213 ((const char *)ef->rela + ef->relasize); 1214 while (rela < relalim) { | 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 } 1212 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) { |
1215 if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, | 1219 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rela, |
1216 ELF_RELOC_RELA, elf_lookup)) { 1217 symname = symbol_name(ef, rela->r_info); 1218 printf("link_elf: symbol %s undefined\n", 1219 symname); 1220 return (ENOENT); 1221 } 1222 rela++; 1223 } 1224 } 1225 1226 /* Perform PLT relocations without addend if there are any: */ 1227 rel = ef->pltrel; 1228 if (rel != NULL) { 1229 rellim = (const Elf_Rel *) 1230 ((const char *)ef->pltrel + ef->pltrelsize); 1231 while (rel < rellim) { | 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 } 1229 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) { |
1232 if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, | 1236 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rel, |
1233 ELF_RELOC_REL, elf_lookup)) { 1234 symname = symbol_name(ef, rel->r_info); 1235 printf("link_elf: symbol %s undefined\n", 1236 symname); 1237 return (ENOENT); 1238 } 1239 rel++; 1240 } 1241 } 1242 1243 /* Perform relocations with addend if there are any: */ 1244 rela = ef->pltrela; 1245 if (rela != NULL) { 1246 relalim = (const Elf_Rela *) 1247 ((const char *)ef->pltrela + ef->pltrelasize); 1248 while (rela < relalim) { | 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 } 1246 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) { |
1249 if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, | 1253 if (elf_reloc_func(&ef->lf, (Elf_Addr)ef->address, rela, |
1250 ELF_RELOC_RELA, elf_lookup)) { 1251 symname = symbol_name(ef, rela->r_info); 1252 printf("link_elf: symbol %s undefined\n", 1253 symname); 1254 return (ENOENT); 1255 } 1256 rela++; 1257 } 1258 } 1259 1260 return (0); 1261} 1262 | 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{ 1270 int e; 1271 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); 1278} 1279 |
|
1263/* 1264 * Hash function for symbol table lookup. Don't even think about changing 1265 * this. It is specified by the System V ABI. 1266 */ 1267static unsigned long 1268elf_hash(const char *name) 1269{ 1270 const unsigned char *p = (const unsigned char *) name; --- 41 unchanged lines hidden (view full) --- 1312 return (ENOENT); 1313 } 1314 1315 strp = ef->strtab + symp->st_name; 1316 1317 if (strcmp(name, strp) == 0) { 1318 if (symp->st_shndx != SHN_UNDEF || 1319 (symp->st_value != 0 && | 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) 1286{ 1287 const unsigned char *p = (const unsigned char *) name; --- 41 unchanged lines hidden (view full) --- 1329 return (ENOENT); 1330 } 1331 1332 strp = ef->strtab + symp->st_name; 1333 1334 if (strcmp(name, strp) == 0) { 1335 if (symp->st_shndx != SHN_UNDEF || 1336 (symp->st_value != 0 && |
1320 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { | 1337 (ELF_ST_TYPE(symp->st_info) == STT_FUNC || 1338 ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC))) { |
1321 *sym = (c_linker_sym_t) symp; 1322 return (0); 1323 } 1324 return (ENOENT); 1325 } 1326 1327 symnum = ef->chains[symnum]; 1328 } 1329 1330 /* If we have not found it, look at the full table (if loaded) */ 1331 if (ef->symtab == ef->ddbsymtab) 1332 return (ENOENT); 1333 1334 /* Exhaustive search */ 1335 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1336 strp = ef->ddbstrtab + symp->st_name; 1337 if (strcmp(name, strp) == 0) { 1338 if (symp->st_shndx != SHN_UNDEF || 1339 (symp->st_value != 0 && | 1339 *sym = (c_linker_sym_t) symp; 1340 return (0); 1341 } 1342 return (ENOENT); 1343 } 1344 1345 symnum = ef->chains[symnum]; 1346 } 1347 1348 /* If we have not found it, look at the full table (if loaded) */ 1349 if (ef->symtab == ef->ddbsymtab) 1350 return (ENOENT); 1351 1352 /* Exhaustive search */ 1353 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1354 strp = ef->ddbstrtab + symp->st_name; 1355 if (strcmp(name, strp) == 0) { 1356 if (symp->st_shndx != SHN_UNDEF || 1357 (symp->st_value != 0 && |
1340 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { | 1358 (ELF_ST_TYPE(symp->st_info) == STT_FUNC || 1359 ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC))) { |
1341 *sym = (c_linker_sym_t) symp; 1342 return (0); 1343 } 1344 return (ENOENT); 1345 } 1346 } 1347 1348 return (ENOENT); 1349} 1350 1351static int 1352link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, 1353 linker_symval_t *symval) 1354{ | 1360 *sym = (c_linker_sym_t) symp; 1361 return (0); 1362 } 1363 return (ENOENT); 1364 } 1365 } 1366 1367 return (ENOENT); 1368} 1369 1370static int 1371link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, 1372 linker_symval_t *symval) 1373{ |
1355 elf_file_t ef = (elf_file_t) lf; 1356 const Elf_Sym* es = (const Elf_Sym*) sym; | 1374 elf_file_t ef; 1375 const Elf_Sym *es; 1376 caddr_t val; |
1357 | 1377 |
1378 ef = (elf_file_t)lf; 1379 es = (const Elf_Sym *)sym; |
|
1358 if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) { 1359 symval->name = ef->strtab + es->st_name; | 1380 if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) { 1381 symval->name = ef->strtab + es->st_name; |
1360 symval->value = (caddr_t) ef->address + es->st_value; | 1382 val = (caddr_t)ef->address + es->st_value; 1383 if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) 1384 val = ((caddr_t (*)(void))val)(); 1385 symval->value = val; |
1361 symval->size = es->st_size; 1362 return (0); 1363 } 1364 if (ef->symtab == ef->ddbsymtab) 1365 return (ENOENT); 1366 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { 1367 symval->name = ef->ddbstrtab + es->st_name; | 1386 symval->size = es->st_size; 1387 return (0); 1388 } 1389 if (ef->symtab == ef->ddbsymtab) 1390 return (ENOENT); 1391 if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { 1392 symval->name = ef->ddbstrtab + es->st_name; |
1368 symval->value = (caddr_t) ef->address + es->st_value; | 1393 val = (caddr_t)ef->address + es->st_value; 1394 if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) 1395 val = ((caddr_t (*)(void))val)(); 1396 symval->value = val; |
1369 symval->size = es->st_size; 1370 return (0); 1371 } 1372 return (ENOENT); 1373} 1374 1375static int 1376link_elf_search_symbol(linker_file_t lf, caddr_t value, --- 93 unchanged lines hidden (view full) --- 1470{ 1471 elf_file_t ef = (elf_file_t)file; 1472 const Elf_Sym *symp; 1473 int i, error; 1474 1475 /* Exhaustive search */ 1476 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1477 if (symp->st_value != 0 && | 1397 symval->size = es->st_size; 1398 return (0); 1399 } 1400 return (ENOENT); 1401} 1402 1403static int 1404link_elf_search_symbol(linker_file_t lf, caddr_t value, --- 93 unchanged lines hidden (view full) --- 1498{ 1499 elf_file_t ef = (elf_file_t)file; 1500 const Elf_Sym *symp; 1501 int i, error; 1502 1503 /* Exhaustive search */ 1504 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1505 if (symp->st_value != 0 && |
1478 ELF_ST_TYPE(symp->st_info) == STT_FUNC) { | 1506 (ELF_ST_TYPE(symp->st_info) == STT_FUNC || 1507 ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC)) { |
1479 error = callback(ef->ddbstrtab + symp->st_name, opaque); 1480 if (error != 0) 1481 return (error); 1482 } 1483 } 1484 return (0); 1485} 1486 --- 4 unchanged lines hidden (view full) --- 1491 linker_symval_t symval; 1492 elf_file_t ef = (elf_file_t)file; 1493 const Elf_Sym* symp; 1494 int i, error; 1495 1496 /* Exhaustive search */ 1497 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1498 if (symp->st_value != 0 && | 1508 error = callback(ef->ddbstrtab + symp->st_name, opaque); 1509 if (error != 0) 1510 return (error); 1511 } 1512 } 1513 return (0); 1514} 1515 --- 4 unchanged lines hidden (view full) --- 1520 linker_symval_t symval; 1521 elf_file_t ef = (elf_file_t)file; 1522 const Elf_Sym* symp; 1523 int i, error; 1524 1525 /* Exhaustive search */ 1526 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { 1527 if (symp->st_value != 0 && |
1499 ELF_ST_TYPE(symp->st_info) == STT_FUNC) { | 1528 (ELF_ST_TYPE(symp->st_info) == STT_FUNC || 1529 ELF_ST_TYPE(symp->st_info) == STT_GNU_IFUNC)) { |
1500 error = link_elf_symbol_values(file, 1501 (c_linker_sym_t) symp, &symval); 1502 if (error != 0) 1503 return (error); 1504 error = callback(file, i, &symval, opaque); 1505 if (error != 0) 1506 return (error); 1507 } --- 142 unchanged lines hidden (view full) --- 1650 1651 *strtab = ef->ddbstrtab; 1652 1653 if (*strtab == NULL) 1654 return (0); 1655 1656 return (ef->ddbstrcnt); 1657} | 1530 error = link_elf_symbol_values(file, 1531 (c_linker_sym_t) symp, &symval); 1532 if (error != 0) 1533 return (error); 1534 error = callback(file, i, &symval, opaque); 1535 if (error != 0) 1536 return (error); 1537 } --- 142 unchanged lines hidden (view full) --- 1680 1681 *strtab = ef->ddbstrtab; 1682 1683 if (*strtab == NULL) 1684 return (0); 1685 1686 return (ef->ddbstrcnt); 1687} |
1688 1689#if defined(__i386__) || defined(__amd64__) 1690void 1691link_elf_ireloc(caddr_t kmdp) 1692{ 1693 struct elf_file eff; 1694 elf_file_t ef; 1695 1696 ef = &eff; 1697 bzero(ef, sizeof(*ef)); 1698 ef->modptr = kmdp; 1699 ef->dynamic = (Elf_Dyn *)&_DYNAMIC; 1700 parse_dynamic(ef); 1701 ef->address = 0; 1702 link_elf_preload_parse_symbols(ef); 1703 relocate_file1(ef, elf_reloc_ifunc); 1704} 1705#endif |
|