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