@@ -79,6 +79,11 @@ static_assert(sizeof(dosProgram) % 8 == 0,
7979
8080static const int dosStubSize = sizeof (dos_header) + sizeof (dosProgram);
8181static_assert (dosStubSize % 8 == 0 , " DOSStub size must be multiple of 8" );
82+ static const uint32_t coffHeaderOffset = dosStubSize + sizeof (PEMagic);
83+ static const uint32_t peHeaderOffset =
84+ coffHeaderOffset + sizeof (coff_file_header);
85+ static const uint32_t dataDirOffset64 =
86+ peHeaderOffset + sizeof (pe32plus_header);
8287
8388static const int numberOfDataDirectory = 16 ;
8489
@@ -272,6 +277,7 @@ class Writer {
272277 OutputSection *findSection (StringRef name);
273278 void addBaserels ();
274279 void addBaserelBlocks (std::vector<Baserel> &v);
280+ void createDynamicRelocs ();
275281
276282 uint32_t getSizeOfInitializedData ();
277283
@@ -754,6 +760,8 @@ void Writer::run() {
754760 llvm::TimeTraceScope timeScope (" Write PE" );
755761 ScopedTimer t1 (ctx.codeLayoutTimer );
756762
763+ if (ctx.config .machine == ARM64X)
764+ ctx.dynamicRelocs = make<DynamicRelocsChunk>();
757765 createImportTables ();
758766 createSections ();
759767 appendImportThunks ();
@@ -764,6 +772,7 @@ void Writer::run() {
764772 mergeSections ();
765773 sortECChunks ();
766774 appendECImportTables ();
775+ createDynamicRelocs ();
767776 removeUnusedSections ();
768777 finalizeAddresses ();
769778 removeEmptySections ();
@@ -1597,8 +1606,14 @@ void Writer::assignAddresses() {
15971606
15981607 for (OutputSection *sec : ctx.outputSections ) {
15991608 llvm::TimeTraceScope timeScope (" Section: " , sec->name );
1600- if (sec == relocSec)
1609+ if (sec == relocSec) {
1610+ sec->chunks .clear ();
16011611 addBaserels ();
1612+ if (ctx.dynamicRelocs ) {
1613+ ctx.dynamicRelocs ->finalize ();
1614+ relocSec->addChunk (ctx.dynamicRelocs );
1615+ }
1616+ }
16021617 uint64_t rawSize = 0 , virtualSize = 0 ;
16031618 sec->header .VirtualAddress = rva;
16041619
@@ -1673,6 +1688,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
16731688 buf += sizeof (PEMagic);
16741689
16751690 // Write COFF header
1691+ assert (coffHeaderOffset == buf - buffer->getBufferStart ());
16761692 auto *coff = reinterpret_cast <coff_file_header *>(buf);
16771693 buf += sizeof (*coff);
16781694 switch (config->machine ) {
@@ -1705,6 +1721,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
17051721 sizeof (PEHeaderTy) + sizeof (data_directory) * numberOfDataDirectory;
17061722
17071723 // Write PE header
1724+ assert (peHeaderOffset == buf - buffer->getBufferStart ());
17081725 auto *pe = reinterpret_cast <PEHeaderTy *>(buf);
17091726 buf += sizeof (*pe);
17101727 pe->Magic = config->is64 () ? PE32Header::PE32_PLUS : PE32Header::PE32;
@@ -1770,6 +1787,8 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
17701787 pe->SizeOfInitializedData = getSizeOfInitializedData ();
17711788
17721789 // Write data directory
1790+ assert (!ctx.config .is64 () ||
1791+ dataDirOffset64 == buf - buffer->getBufferStart ());
17731792 auto *dir = reinterpret_cast <data_directory *>(buf);
17741793 buf += sizeof (*dir) * numberOfDataDirectory;
17751794 if (edataStart) {
@@ -1799,9 +1818,12 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
17991818 exceptionTable.last ->getSize () -
18001819 exceptionTable.first ->getRVA ();
18011820 }
1802- if (relocSec->getVirtualSize ()) {
1821+ size_t relocSize = relocSec->getVirtualSize ();
1822+ if (ctx.dynamicRelocs )
1823+ relocSize -= ctx.dynamicRelocs ->getSize ();
1824+ if (relocSize) {
18031825 dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA ();
1804- dir[BASE_RELOCATION_TABLE].Size = relocSec-> getVirtualSize () ;
1826+ dir[BASE_RELOCATION_TABLE].Size = relocSize ;
18051827 }
18061828 if (Symbol *sym = ctx.symtab .findUnderscore (" _tls_used" )) {
18071829 if (Defined *b = dyn_cast<Defined>(sym)) {
@@ -2523,7 +2545,6 @@ uint32_t Writer::getSizeOfInitializedData() {
25232545void Writer::addBaserels () {
25242546 if (!ctx.config .relocatable )
25252547 return ;
2526- relocSec->chunks .clear ();
25272548 std::vector<Baserel> v;
25282549 for (OutputSection *sec : ctx.outputSections ) {
25292550 if (sec->header .Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
@@ -2557,6 +2578,29 @@ void Writer::addBaserelBlocks(std::vector<Baserel> &v) {
25572578 relocSec->addChunk (make<BaserelChunk>(page, &v[i], &v[0 ] + j));
25582579}
25592580
2581+ void Writer::createDynamicRelocs () {
2582+ if (!ctx.dynamicRelocs )
2583+ return ;
2584+
2585+ // Adjust the Machine field in the COFF header to AMD64.
2586+ ctx.dynamicRelocs ->add (IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof (uint16_t ),
2587+ coffHeaderOffset + offsetof (coff_file_header, Machine),
2588+ AMD64);
2589+
2590+ // Clear the load config directory.
2591+ // FIXME: Use the hybrid load config value instead.
2592+ ctx.dynamicRelocs ->add (IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof (uint32_t ),
2593+ dataDirOffset64 +
2594+ LOAD_CONFIG_TABLE * sizeof (data_directory) +
2595+ offsetof (data_directory, RelativeVirtualAddress),
2596+ 0 );
2597+ ctx.dynamicRelocs ->add (IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof (uint32_t ),
2598+ dataDirOffset64 +
2599+ LOAD_CONFIG_TABLE * sizeof (data_directory) +
2600+ offsetof (data_directory, Size),
2601+ 0 );
2602+ }
2603+
25602604PartialSection *Writer::createPartialSection (StringRef name,
25612605 uint32_t outChars) {
25622606 PartialSection *&pSec = partialSections[{name, outChars}];
@@ -2660,6 +2704,18 @@ template <typename T> void Writer::prepareLoadConfig(T *loadConfig) {
26602704 loadConfig->DependentLoadFlags = ctx.config .dependentLoadFlags ;
26612705 }
26622706
2707+ if (ctx.dynamicRelocs ) {
2708+ IF_CONTAINS (DynamicValueRelocTableSection) {
2709+ loadConfig->DynamicValueRelocTableSection = relocSec->sectionIndex ;
2710+ loadConfig->DynamicValueRelocTableOffset =
2711+ ctx.dynamicRelocs ->getRVA () - relocSec->getRVA ();
2712+ }
2713+ else {
2714+ warn (" '_load_config_used' structure too small to include dynamic "
2715+ " relocations" );
2716+ }
2717+ }
2718+
26632719 if (ctx.config .guardCF == GuardCFLevel::Off)
26642720 return ;
26652721 RETURN_IF_NOT_CONTAINS (GuardFlags)
0 commit comments