Changeset 46259 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- May 24, 2013 7:20:19 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 85993
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
r46180 r46259 99 99 /** The ELF header. */ 100 100 Elf_Ehdr Ehdr; 101 /** Pointer to our copy of the section headers .101 /** Pointer to our copy of the section headers with sh_addr as RVAs. 102 102 * The virtual addresses in this array is the 0 based assignments we've given the image. 103 103 * Not valid if the image is DONE. */ … … 108 108 /** The size of the loaded image. */ 109 109 size_t cbImage; 110 111 /** The image base address if it's an EXEC or DYN image. */ 112 Elf_Addr LinkAddress; 110 113 111 114 /** The symbol section index. */ … … 156 159 } 157 160 161 162 /* 163 * 164 * EXEC & DYN. 165 * EXEC & DYN. 166 * EXEC & DYN. 167 * EXEC & DYN. 168 * EXEC & DYN. 169 * 170 */ 171 172 173 /** 174 * Applies the fixups for a section in an executable image. 175 * 176 * @returns iprt status code. 177 * @param pModElf The ELF loader module instance data. 178 * @param BaseAddr The base address which the module is being fixedup to. 179 * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals). 180 * @param pvUser User argument to pass to the callback. 181 * @param SecAddr The section address. This is the address the relocations are relative to. 182 * @param cbSec The section size. The relocations must be inside this. 183 * @param pu8SecBaseR Where we read section bits from. 184 * @param pu8SecBaseW Where we write section bits to. 185 * @param pvRelocs Pointer to where we read the relocations from. 186 * @param cbRelocs Size of the relocations. 187 */ 188 static int RTLDRELF_NAME(RelocateSectionExecDyn)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, 189 PFNRTLDRIMPORT pfnGetImport, void *pvUser, 190 const Elf_Addr SecAddr, Elf_Size cbSec, 191 const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW, 192 const void *pvRelocs, Elf_Size cbRelocs) 193 { 194 #if ELF_MODE != 32 195 NOREF(pu8SecBaseR); 196 #endif 197 198 /* 199 * Iterate the relocations. 200 * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section. 201 */ 202 const Elf_Addr offDelta = BaseAddr - pModElf->LinkAddress; 203 const Elf_Reloc *paRels = (const Elf_Reloc *)pvRelocs; 204 const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0])); 205 AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])), 206 VERR_IMAGE_TOO_BIG); 207 for (unsigned iRel = 0; iRel < iRelMax; iRel++) 208 { 209 /* 210 * Skip R_XXX_NONE entries early to avoid confusion in the symbol 211 * getter code. 212 */ 213 #if ELF_MODE == 32 214 if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE) 215 continue; 216 #elif ELF_MODE == 64 217 if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE) 218 continue; 219 #endif 220 221 /* 222 * Validate and find the symbol, resolve undefined ones. 223 */ 224 Elf_Size iSym = ELF_R_SYM(paRels[iRel].r_info); 225 if (iSym >= pModElf->cSyms) 226 { 227 AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym)); 228 return VERR_LDRELF_INVALID_SYMBOL_INDEX; 229 } 230 const Elf_Sym *pSym = &pModElf->paSyms[iSym]; 231 if (pSym->st_name >= pModElf->cbStr) 232 { 233 AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr)); 234 return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET; 235 } 236 237 Elf_Addr SymValue = 0; 238 if (pSym->st_shndx == SHN_UNDEF) 239 { 240 /* Try to resolve the symbol. */ 241 const char *pszName = ELF_STR(pModElf, pSym->st_name); 242 RTUINTPTR ExtValue; 243 int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0, &ExtValue, pvUser); 244 AssertMsgRCReturn(rc, ("Failed to resolve '%s' rc=%Rrc\n", pszName, rc), rc); 245 SymValue = (Elf_Addr)ExtValue; 246 AssertMsgReturn((RTUINTPTR)SymValue == ExtValue, ("Symbol value overflowed! '%s'\n", pszName), 247 VERR_SYMBOL_VALUE_TOO_BIG); 248 Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, SymValue, pszName)); 249 } 250 else 251 { 252 AssertReturn(pSym->st_shndx < pModElf->cSyms || pSym->st_shndx == SHN_ABS, ("%#x\n", pSym->st_shndx)); 253 #if ELF_MODE == 64 254 SymValue = pSym->st_value; 255 #endif 256 } 257 258 #if ELF_MODE == 64 259 /* Calc the value. */ 260 Elf_Addr Value; 261 if (pSym->st_shndx < pModElf->cSyms) 262 Value = SymValue + offDelta; 263 else 264 Value = SymValue + paRels[iRel].r_addend; 265 #endif 266 267 /* 268 * Apply the fixup. 269 */ 270 AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET); 271 #if ELF_MODE == 32 272 const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset); /* Where to read the addend. */ 273 #endif 274 Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */ 275 switch (ELF_R_TYPE(paRels[iRel].r_info)) 276 { 277 #if ELF_MODE == 32 278 /* 279 * Absolute addressing. 280 */ 281 case R_386_32: 282 { 283 Elf_Addr Value; 284 if (pSym->st_shndx < pModElf->Ehdr.e_shnum) 285 Value = *pAddrR + offDelta; /* Simplified. */ 286 else if (pSym->st_shndx == SHN_ABS) 287 continue; /* Internal fixup, no need to apply it. */ 288 else if (pSym->st_shndx == SHN_UNDEF) 289 Value = SymValue + *pAddrR; 290 else 291 AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */ 292 *(uint32_t *)pAddrW = Value; 293 Log4((FMT_ELF_ADDR": R_386_32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value)); 294 break; 295 } 296 297 /* 298 * PC relative addressing. 299 */ 300 case R_386_PC32: 301 { 302 Elf_Addr Value; 303 if (pSym->st_shndx < pModElf->Ehdr.e_shnum) 304 continue; /* Internal fixup, no need to apply it. */ 305 else if (pSym->st_shndx == SHN_ABS) 306 Value = *pAddrR + offDelta; /* Simplified. */ 307 else if (pSym->st_shndx == SHN_UNDEF) 308 { 309 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */ 310 Value = SymValue + *(uint32_t *)pAddrR - SourceAddr; 311 *(uint32_t *)pAddrW = Value; 312 } 313 else 314 AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */ 315 Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value)); 316 break; 317 } 318 319 #elif ELF_MODE == 64 320 321 /* 322 * Absolute addressing 323 */ 324 case R_X86_64_64: 325 { 326 *(uint64_t *)pAddrW = Value; 327 Log4((FMT_ELF_ADDR": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n", 328 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue)); 329 break; 330 } 331 332 /* 333 * Truncated 32-bit value (zero-extendedable to the 64-bit value). 334 */ 335 case R_X86_64_32: 336 { 337 *(uint32_t *)pAddrW = (uint32_t)Value; 338 Log4((FMT_ELF_ADDR": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n", 339 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue)); 340 AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == SymValue, ("Value=" FMT_ELF_ADDR "\n", SymValue), 341 VERR_SYMBOL_VALUE_TOO_BIG); 342 break; 343 } 344 345 /* 346 * Truncated 32-bit value (sign-extendedable to the 64-bit value). 347 */ 348 case R_X86_64_32S: 349 { 350 *(int32_t *)pAddrW = (int32_t)Value; 351 Log4((FMT_ELF_ADDR": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n", 352 SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue)); 353 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */ 354 break; 355 } 356 357 /* 358 * PC relative addressing. 359 */ 360 case R_X86_64_PC32: 361 { 362 const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */ 363 Value -= SourceAddr; 364 *(int32_t *)pAddrW = (int32_t)Value; 365 Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n", 366 SourceAddr, Value, SymValue)); 367 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */ 368 break; 369 } 370 #endif 371 372 default: 373 AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n", 374 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax)); 375 return VERR_LDRELF_RELOCATION_NOT_SUPPORTED; 376 } 377 } 378 379 return VINF_SUCCESS; 380 } 381 382 383 384 /* 385 * 386 * REL 387 * REL 388 * REL 389 * REL 390 * REL 391 * 392 */ 158 393 159 394 /** … … 287 522 { 288 523 /* 524 * Skip R_XXX_NONE entries early to avoid confusion in the symbol 525 * getter code. 526 */ 527 #if ELF_MODE == 32 528 if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE) 529 continue; 530 #elif ELF_MODE == 64 531 if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE) 532 continue; 533 #endif 534 535 536 /* 289 537 * Get the symbol. 290 538 */ … … 476 724 Value = paSyms[iSym].st_value; 477 725 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum) 478 /* relative to the section. */ 479 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr; 726 { 727 if (pModElf->Ehdr.e_type == ET_REL) 728 /* relative to the section. */ 729 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr; 730 else /* Fixed up for link address. */ 731 Value = BaseAddr + paSyms[iSym].st_value - pModElf->LinkAddress; 732 } 480 733 else 481 734 { … … 646 899 647 900 /** @todo Make RelocateSection a function pointer so we can select the one corresponding to the machine when opening the image. */ 648 rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser, 649 pShdr->sh_addr, 650 pShdr->sh_size, 651 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset, 652 (uint8_t *)pvBits + pShdr->sh_addr, 653 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset, 654 pShdrRel->sh_size); 901 if (pModElf->Ehdr.e_type == ET_REL) 902 rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser, 903 pShdr->sh_addr, 904 pShdr->sh_size, 905 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset, 906 (uint8_t *)pvBits + pShdr->sh_addr, 907 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset, 908 pShdrRel->sh_size); 909 else 910 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser, 911 pShdr->sh_addr, 912 pShdr->sh_size, 913 (const uint8_t *)pModElf->pvBits + pShdr->sh_offset, 914 (uint8_t *)pvBits + pShdr->sh_addr, 915 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset, 916 pShdrRel->sh_size); 655 917 if (RT_FAILURE(rc)) 656 918 return rc; … … 703 965 Value = paSyms[iSym].st_value; 704 966 else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum) 705 /* relative to the section. */ 706 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr; 967 { 968 if (pModElf->Ehdr.e_type == ET_REL) 969 /* relative to the section. */ 970 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr; 971 else /* Fixed up for link address. */ 972 Value = BaseAddr + paSyms[iSym].st_value - pModElf->LinkAddress; 973 } 707 974 else 708 975 { … … 998 1265 { 999 1266 PRTLDRMODELF pThis = (PRTLDRMODELF)pMod; 1267 LogFlow(("%s: iDbgInfo=%#x off=%RTfoff cb=%#zu\n", __FUNCTION__, iDbgInfo, off, cb)); 1000 1268 1001 1269 /* … … 1066 1334 * Apply the relocations. 1067 1335 */ 1068 rc = RTLDRELF_NAME(RelocateSection)(pThis, 0 /*BaseAddress*/, 1069 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/, 1070 pThis->paShdrs[iDbgInfo].sh_addr, 1071 pThis->paShdrs[iDbgInfo].sh_size, 1072 (const uint8_t *)pvBuf, 1073 (uint8_t *)pvBuf, 1074 pbRelocs, 1075 pThis->paShdrs[iRelocs].sh_size); 1336 if (pThis->Ehdr.e_type == ET_REL) 1337 rc = RTLDRELF_NAME(RelocateSection)(pThis, pThis->LinkAddress, 1338 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/, 1339 pThis->paShdrs[iDbgInfo].sh_addr, 1340 pThis->paShdrs[iDbgInfo].sh_size, 1341 (const uint8_t *)pvBuf, 1342 (uint8_t *)pvBuf, 1343 pbRelocs, 1344 pThis->paShdrs[iRelocs].sh_size); 1345 else 1346 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pThis, pThis->LinkAddress, 1347 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/, 1348 pThis->paShdrs[iDbgInfo].sh_addr, 1349 pThis->paShdrs[iDbgInfo].sh_size, 1350 (const uint8_t *)pvBuf, 1351 (uint8_t *)pvBuf, 1352 pbRelocs, 1353 pThis->paShdrs[iRelocs].sh_size); 1354 1076 1355 RTMemTmpFree(pbRelocsBuf); 1077 1356 } … … 1455 1734 //pModElf->cbStr = 0; 1456 1735 //pModElf->cbImage = 0; 1736 //pModElf->LinkAddress = 0; 1457 1737 //pModElf->pStr = NULL; 1458 1738 //pModElf->cbShStr = 0; … … 1494 1774 1495 1775 /* 1496 * Validate the section headers, allocate memory for the sections (determine the image size), 1497 * and find relevant sections. 1776 * Validate the section headers and find relevant sections. 1498 1777 */ 1499 1778 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++) … … 1502 1781 if (RT_FAILURE(rc)) 1503 1782 break; 1504 1505 /* Allocate memory addresses for the section. */1506 if (paShdrs[i].sh_flags & SHF_ALLOC)1507 {1508 paShdrs[i].sh_addr = paShdrs[i].sh_addralign1509 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)1510 : (Elf_Addr)pModElf->cbImage;1511 pModElf->cbImage = (size_t)paShdrs[i].sh_addr + (size_t)paShdrs[i].sh_size;1512 AssertMsgReturn(pModElf->cbImage == paShdrs[i].sh_addr + paShdrs[i].sh_size,1513 (FMT_ELF_ADDR "\n", paShdrs[i].sh_addr + paShdrs[i].sh_size),1514 VERR_IMAGE_TOO_BIG);1515 Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));1516 }1517 1783 1518 1784 /* We're looking for symbol tables. */ … … 1552 1818 } /* for each section header */ 1553 1819 1554 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx\n", 1555 pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc, pModElf->cbImage)); 1820 /* 1821 * Calculate the image base address if the image isn't relocatable. 1822 */ 1823 if (RT_SUCCESS(rc) && pModElf->Ehdr.e_type != ET_REL) 1824 { 1825 pModElf->LinkAddress = ~(Elf_Addr)0; 1826 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++) 1827 if ( (paShdrs[i].sh_flags & SHF_ALLOC) 1828 && paShdrs[i].sh_addr < pModElf->LinkAddress) 1829 pModElf->LinkAddress = paShdrs[i].sh_addr; 1830 if (pModElf->LinkAddress == ~(Elf_Addr)0) 1831 { 1832 AssertFailed(); 1833 rc = VERR_LDR_GENERAL_FAILURE; 1834 } 1835 } 1836 1837 /* 1838 * Perform allocations / RVA calculations, determine the image size. 1839 */ 1840 if (RT_SUCCESS(rc)) 1841 for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++) 1842 if (paShdrs[i].sh_flags & SHF_ALLOC) 1843 { 1844 if (pModElf->Ehdr.e_type == ET_REL) 1845 paShdrs[i].sh_addr = paShdrs[i].sh_addralign 1846 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr) 1847 : (Elf_Addr)pModElf->cbImage; 1848 else 1849 paShdrs[i].sh_addr -= pModElf->LinkAddress; 1850 Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size; 1851 if (pModElf->cbImage < EndAddr) 1852 { 1853 pModElf->cbImage = (size_t)EndAddr; 1854 AssertMsgReturn(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), VERR_IMAGE_TOO_BIG); 1855 } 1856 Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i)); 1857 } 1858 1859 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n", 1860 pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc, 1861 pModElf->cbImage, pModElf->LinkAddress)); 1556 1862 if (RT_SUCCESS(rc)) 1557 1863 {
Note:
See TracChangeset
for help on using the changeset viewer.