Mercurial > hg > CbC > CbC_llvm
comparison lld/ELF/Writer.cpp @ 207:2e18cbf3894f
LLVM12
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 08 Jun 2021 06:07:14 +0900 |
parents | 0572611fdcc8 |
children | 5f17cb93ff66 |
comparison
equal
deleted
inserted
replaced
173:0572611fdcc8 | 207:2e18cbf3894f |
---|---|
17 #include "Relocations.h" | 17 #include "Relocations.h" |
18 #include "SymbolTable.h" | 18 #include "SymbolTable.h" |
19 #include "Symbols.h" | 19 #include "Symbols.h" |
20 #include "SyntheticSections.h" | 20 #include "SyntheticSections.h" |
21 #include "Target.h" | 21 #include "Target.h" |
22 #include "lld/Common/Arrays.h" | |
22 #include "lld/Common/Filesystem.h" | 23 #include "lld/Common/Filesystem.h" |
23 #include "lld/Common/Memory.h" | 24 #include "lld/Common/Memory.h" |
24 #include "lld/Common/Strings.h" | 25 #include "lld/Common/Strings.h" |
25 #include "llvm/ADT/StringMap.h" | 26 #include "llvm/ADT/StringMap.h" |
26 #include "llvm/ADT/StringSwitch.h" | 27 #include "llvm/ADT/StringSwitch.h" |
43 | 44 |
44 namespace { | 45 namespace { |
45 // The writer writes a SymbolTable result to a file. | 46 // The writer writes a SymbolTable result to a file. |
46 template <class ELFT> class Writer { | 47 template <class ELFT> class Writer { |
47 public: | 48 public: |
49 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) | |
50 | |
48 Writer() : buffer(errorHandler().outputBuffer) {} | 51 Writer() : buffer(errorHandler().outputBuffer) {} |
49 using Elf_Shdr = typename ELFT::Shdr; | |
50 using Elf_Ehdr = typename ELFT::Ehdr; | |
51 using Elf_Phdr = typename ELFT::Phdr; | |
52 | 52 |
53 void run(); | 53 void run(); |
54 | 54 |
55 private: | 55 private: |
56 void copyLocalSymbols(); | 56 void copyLocalSymbols(); |
129 // sortISDBySectionOrder(). | 129 // sortISDBySectionOrder(). |
130 // ".text.unknown" means the hotness of the section is unknown. When | 130 // ".text.unknown" means the hotness of the section is unknown. When |
131 // SampleFDO is used, if a function doesn't have sample, it could be very | 131 // SampleFDO is used, if a function doesn't have sample, it could be very |
132 // cold or it could be a new function never being sampled. Those functions | 132 // cold or it could be a new function never being sampled. Those functions |
133 // will be kept in the ".text.unknown" section. | 133 // will be kept in the ".text.unknown" section. |
134 // ".text.split." holds symbols which are split out from functions in other | |
135 // input sections. For example, with -fsplit-machine-functions, placing the | |
136 // cold parts in .text.split instead of .text.unlikely mitigates against poor | |
137 // profile inaccuracy. Techniques such as hugepage remapping can make | |
138 // conservative decisions at the section granularity. | |
134 if (config->zKeepTextSectionPrefix) | 139 if (config->zKeepTextSectionPrefix) |
135 for (StringRef v : {".text.hot.", ".text.unknown.", ".text.unlikely.", | 140 for (StringRef v : {".text.hot.", ".text.unknown.", ".text.unlikely.", |
136 ".text.startup.", ".text.exit."}) | 141 ".text.startup.", ".text.exit.", ".text.split."}) |
137 if (isSectionPrefix(v, s->name)) | 142 if (isSectionPrefix(v, s->name)) |
138 return v.drop_back(); | 143 return v.drop_back(); |
139 | 144 |
140 for (StringRef v : | 145 for (StringRef v : |
141 {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", | 146 {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", |
151 return !config->relocatable && !config->shared && | 156 return !config->relocatable && !config->shared && |
152 !config->dynamicLinker.empty() && script->needsInterpSection(); | 157 !config->dynamicLinker.empty() && script->needsInterpSection(); |
153 } | 158 } |
154 | 159 |
155 template <class ELFT> void elf::writeResult() { | 160 template <class ELFT> void elf::writeResult() { |
156 llvm::TimeTraceScope timeScope("Write output file"); | |
157 Writer<ELFT>().run(); | 161 Writer<ELFT>().run(); |
158 } | 162 } |
159 | 163 |
160 static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) { | 164 static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) { |
161 auto it = std::stable_partition( | 165 auto it = std::stable_partition( |
198 inputSections.insert(inputSections.end(), newSections.begin(), | 202 inputSections.insert(inputSections.end(), newSections.begin(), |
199 newSections.end()); | 203 newSections.end()); |
200 } | 204 } |
201 | 205 |
202 void elf::combineEhSections() { | 206 void elf::combineEhSections() { |
207 llvm::TimeTraceScope timeScope("Combine EH sections"); | |
203 for (InputSectionBase *&s : inputSections) { | 208 for (InputSectionBase *&s : inputSections) { |
204 // Ignore dead sections and the partition end marker (.part.end), | 209 // Ignore dead sections and the partition end marker (.part.end), |
205 // whose partition number is out of bounds. | 210 // whose partition number is out of bounds. |
206 if (!s->isLive() || s->partition == 255) | 211 if (!s->isLive() || s->partition == 255) |
207 continue; | 212 continue; |
262 ElfSym::mipsLocalGp = addAbsolute("__gnu_local_gp"); | 267 ElfSym::mipsLocalGp = addAbsolute("__gnu_local_gp"); |
263 } else if (config->emachine == EM_PPC) { | 268 } else if (config->emachine == EM_PPC) { |
264 // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't | 269 // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't |
265 // support Small Data Area, define it arbitrarily as 0. | 270 // support Small Data Area, define it arbitrarily as 0. |
266 addOptionalRegular("_SDA_BASE_", nullptr, 0, STV_HIDDEN); | 271 addOptionalRegular("_SDA_BASE_", nullptr, 0, STV_HIDDEN); |
272 } else if (config->emachine == EM_PPC64) { | |
273 addPPC64SaveRestore(); | |
267 } | 274 } |
268 | 275 |
269 // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which | 276 // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which |
270 // combines the typical ELF GOT with the small data sections. It commonly | 277 // combines the typical ELF GOT with the small data sections. It commonly |
271 // includes .got .toc .sdata .sbss. The .TOC. symbol replaces both | 278 // includes .got .toc .sdata .sbss. The .TOC. symbol replaces both |
627 checkSections(); | 634 checkSections(); |
628 | 635 |
629 // It does not make sense try to open the file if we have error already. | 636 // It does not make sense try to open the file if we have error already. |
630 if (errorCount()) | 637 if (errorCount()) |
631 return; | 638 return; |
632 // Write the result down to a file. | 639 |
633 openFile(); | 640 { |
634 if (errorCount()) | 641 llvm::TimeTraceScope timeScope("Write output file"); |
635 return; | 642 // Write the result down to a file. |
636 | 643 openFile(); |
637 if (!config->oFormatBinary) { | 644 if (errorCount()) |
638 if (config->zSeparate != SeparateSegmentKind::None) | 645 return; |
639 writeTrapInstr(); | 646 |
640 writeHeader(); | 647 if (!config->oFormatBinary) { |
641 writeSections(); | 648 if (config->zSeparate != SeparateSegmentKind::None) |
642 } else { | 649 writeTrapInstr(); |
643 writeSectionsBinary(); | 650 writeHeader(); |
644 } | 651 writeSections(); |
645 | 652 } else { |
646 // Backfill .note.gnu.build-id section content. This is done at last | 653 writeSectionsBinary(); |
647 // because the content is usually a hash value of the entire output file. | 654 } |
648 writeBuildId(); | 655 |
649 if (errorCount()) | 656 // Backfill .note.gnu.build-id section content. This is done at last |
650 return; | 657 // because the content is usually a hash value of the entire output file. |
651 | 658 writeBuildId(); |
652 if (auto e = buffer->commit()) | 659 if (errorCount()) |
653 error("failed to write to the output file: " + toString(std::move(e))); | 660 return; |
661 | |
662 if (auto e = buffer->commit()) | |
663 error("failed to write to the output file: " + toString(std::move(e))); | |
664 } | |
654 } | 665 } |
655 | 666 |
656 template <class ELFT, class RelTy> | 667 template <class ELFT, class RelTy> |
657 static void markUsedLocalSymbolsImpl(ObjFile<ELFT> *file, | 668 static void markUsedLocalSymbolsImpl(ObjFile<ELFT> *file, |
658 llvm::ArrayRef<RelTy> rels) { | 669 llvm::ArrayRef<RelTy> rels) { |
754 // Local symbols are not in the linker's symbol table. This function scans | 765 // Local symbols are not in the linker's symbol table. This function scans |
755 // each object file's symbol table to copy local symbols to the output. | 766 // each object file's symbol table to copy local symbols to the output. |
756 template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { | 767 template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { |
757 if (!in.symTab) | 768 if (!in.symTab) |
758 return; | 769 return; |
770 llvm::TimeTraceScope timeScope("Add local symbols"); | |
759 if (config->copyRelocs && config->discard != DiscardPolicy::None) | 771 if (config->copyRelocs && config->discard != DiscardPolicy::None) |
760 markUsedLocalSymbols<ELFT>(); | 772 markUsedLocalSymbols<ELFT>(); |
761 for (InputFile *file : objectFiles) { | 773 for (InputFile *file : objectFiles) { |
762 ObjFile<ELFT> *f = cast<ObjFile<ELFT>>(file); | 774 ObjFile<ELFT> *f = cast<ObjFile<ELFT>>(file); |
763 for (Symbol *b : f->getLocalSymbols()) { | 775 for (Symbol *b : f->getLocalSymbols()) { |
764 if (!b->isLocal()) | 776 assert(b->isLocal() && "should have been caught in initializeSymbols()"); |
765 fatal(toString(f) + | |
766 ": broken object: getLocalSymbols returns a non-local symbol"); | |
767 auto *dr = dyn_cast<Defined>(b); | 777 auto *dr = dyn_cast<Defined>(b); |
768 | 778 |
769 // No reason to keep local undefined symbol in symtab. | 779 // No reason to keep local undefined symbol in symtab. |
770 if (!dr) | 780 if (!dr) |
771 continue; | 781 continue; |
804 // copied from input sections, and there may be a relocation pointing to its | 814 // copied from input sections, and there may be a relocation pointing to its |
805 // contents if -r or -emit-reloc are given. | 815 // contents if -r or -emit-reloc are given. |
806 if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE)) | 816 if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE)) |
807 continue; | 817 continue; |
808 | 818 |
819 // Set the symbol to be relative to the output section so that its st_value | |
820 // equals the output section address. Note, there may be a gap between the | |
821 // start of the output section and isec. | |
809 auto *sym = | 822 auto *sym = |
810 make<Defined>(isec->file, "", STB_LOCAL, /*stOther=*/0, STT_SECTION, | 823 make<Defined>(isec->file, "", STB_LOCAL, /*stOther=*/0, STT_SECTION, |
811 /*value=*/0, /*size=*/0, isec); | 824 /*value=*/0, /*size=*/0, isec->getOutputSection()); |
812 in.symTab->addSymbol(sym); | 825 in.symTab->addSymbol(sym); |
813 } | 826 } |
814 } | 827 } |
815 | 828 |
816 // Today's loaders have a feature to make segments read-only after | 829 // Today's loaders have a feature to make segments read-only after |
1277 return i; | 1290 return i; |
1278 } | 1291 } |
1279 | 1292 |
1280 // Adds random priorities to sections not already in the map. | 1293 // Adds random priorities to sections not already in the map. |
1281 static void maybeShuffle(DenseMap<const InputSectionBase *, int> &order) { | 1294 static void maybeShuffle(DenseMap<const InputSectionBase *, int> &order) { |
1282 if (!config->shuffleSectionSeed) | 1295 if (config->shuffleSections.empty()) |
1283 return; | 1296 return; |
1284 | 1297 |
1285 std::vector<int> priorities(inputSections.size() - order.size()); | 1298 std::vector<InputSectionBase *> matched, sections = inputSections; |
1299 matched.reserve(sections.size()); | |
1300 for (const auto &patAndSeed : config->shuffleSections) { | |
1301 matched.clear(); | |
1302 for (InputSectionBase *sec : sections) | |
1303 if (patAndSeed.first.match(sec->name)) | |
1304 matched.push_back(sec); | |
1305 const uint32_t seed = patAndSeed.second; | |
1306 if (seed == UINT32_MAX) { | |
1307 // If --shuffle-sections <section-glob>=-1, reverse the section order. The | |
1308 // section order is stable even if the number of sections changes. This is | |
1309 // useful to catch issues like static initialization order fiasco | |
1310 // reliably. | |
1311 std::reverse(matched.begin(), matched.end()); | |
1312 } else { | |
1313 std::mt19937 g(seed ? seed : std::random_device()()); | |
1314 llvm::shuffle(matched.begin(), matched.end(), g); | |
1315 } | |
1316 size_t i = 0; | |
1317 for (InputSectionBase *&sec : sections) | |
1318 if (patAndSeed.first.match(sec->name)) | |
1319 sec = matched[i++]; | |
1320 } | |
1321 | |
1286 // Existing priorities are < 0, so use priorities >= 0 for the missing | 1322 // Existing priorities are < 0, so use priorities >= 0 for the missing |
1287 // sections. | 1323 // sections. |
1288 int curPrio = 0; | 1324 int prio = 0; |
1289 for (int &prio : priorities) | 1325 for (InputSectionBase *sec : sections) { |
1290 prio = curPrio++; | 1326 if (order.try_emplace(sec, prio).second) |
1291 uint32_t seed = *config->shuffleSectionSeed; | 1327 ++prio; |
1292 std::mt19937 g(seed ? seed : std::random_device()()); | |
1293 llvm::shuffle(priorities.begin(), priorities.end(), g); | |
1294 int prioIndex = 0; | |
1295 for (InputSectionBase *sec : inputSections) { | |
1296 if (order.try_emplace(sec, priorities[prioIndex]).second) | |
1297 ++prioIndex; | |
1298 } | 1328 } |
1299 } | 1329 } |
1300 | 1330 |
1301 // Builds section order for handling --symbol-ordering-file. | 1331 // Builds section order for handling --symbol-ordering-file. |
1302 static DenseMap<const InputSectionBase *, int> buildSectionOrder() { | 1332 static DenseMap<const InputSectionBase *, int> buildSectionOrder() { |
1344 for (Symbol *sym : symtab->symbols()) | 1374 for (Symbol *sym : symtab->symbols()) |
1345 if (!sym->isLazy()) | 1375 if (!sym->isLazy()) |
1346 addSym(*sym); | 1376 addSym(*sym); |
1347 | 1377 |
1348 for (InputFile *file : objectFiles) | 1378 for (InputFile *file : objectFiles) |
1349 for (Symbol *sym : file->getSymbols()) | 1379 for (Symbol *sym : file->getSymbols()) { |
1350 if (sym->isLocal()) | 1380 if (!sym->isLocal()) |
1351 addSym(*sym); | 1381 break; |
1382 addSym(*sym); | |
1383 } | |
1352 | 1384 |
1353 if (config->warnSymbolOrdering) | 1385 if (config->warnSymbolOrdering) |
1354 for (auto orderEntry : symbolOrder) | 1386 for (auto orderEntry : symbolOrder) |
1355 if (!orderEntry.second.present) | 1387 if (!orderEntry.second.present) |
1356 warn("symbol ordering file: no such symbol: " + orderEntry.first); | 1388 warn("symbol ordering file: no such symbol: " + orderEntry.first); |
1429 | 1461 |
1430 // Never sort these. | 1462 // Never sort these. |
1431 if (name == ".init" || name == ".fini") | 1463 if (name == ".init" || name == ".fini") |
1432 return; | 1464 return; |
1433 | 1465 |
1466 // IRelative relocations that usually live in the .rel[a].dyn section should | |
1467 // be processed last by the dynamic loader. To achieve that we add synthetic | |
1468 // sections in the required order from the beginning so that the in.relaIplt | |
1469 // section is placed last in an output section. Here we just do not apply | |
1470 // sorting for an output section which holds the in.relaIplt section. | |
1471 if (in.relaIplt->getParent() == sec) | |
1472 return; | |
1473 | |
1434 // Sort input sections by priority using the list provided by | 1474 // Sort input sections by priority using the list provided by |
1435 // --symbol-ordering-file or --shuffle-sections=. This is a least significant | 1475 // --symbol-ordering-file or --shuffle-sections=. This is a least significant |
1436 // digit radix sort. The sections may be sorted stably again by a more | 1476 // digit radix sort. The sections may be sorted stably again by a more |
1437 // significant key. | 1477 // significant key. |
1438 if (!order.empty()) | 1478 if (!order.empty()) |
1484 if (auto *sec = dyn_cast<OutputSection>(base)) | 1524 if (auto *sec = dyn_cast<OutputSection>(base)) |
1485 sortSection(sec, order); | 1525 sortSection(sec, order); |
1486 } | 1526 } |
1487 | 1527 |
1488 template <class ELFT> void Writer<ELFT>::sortSections() { | 1528 template <class ELFT> void Writer<ELFT>::sortSections() { |
1529 llvm::TimeTraceScope timeScope("Sort sections"); | |
1489 script->adjustSectionsBeforeSorting(); | 1530 script->adjustSectionsBeforeSorting(); |
1490 | 1531 |
1491 // Don't sort if using -r. It is not necessary and we want to preserve the | 1532 // Don't sort if using -r. It is not necessary and we want to preserve the |
1492 // relative order for SHF_LINK_ORDER sections. | 1533 // relative order for SHF_LINK_ORDER sections. |
1493 if (config->relocatable) | 1534 if (config->relocatable) |
1602 | 1643 |
1603 script->adjustSectionsAfterSorting(); | 1644 script->adjustSectionsAfterSorting(); |
1604 } | 1645 } |
1605 | 1646 |
1606 static bool compareByFilePosition(InputSection *a, InputSection *b) { | 1647 static bool compareByFilePosition(InputSection *a, InputSection *b) { |
1607 InputSection *la = a->getLinkOrderDep(); | 1648 InputSection *la = a->flags & SHF_LINK_ORDER ? a->getLinkOrderDep() : nullptr; |
1608 InputSection *lb = b->getLinkOrderDep(); | 1649 InputSection *lb = b->flags & SHF_LINK_ORDER ? b->getLinkOrderDep() : nullptr; |
1650 // SHF_LINK_ORDER sections with non-zero sh_link are ordered before | |
1651 // non-SHF_LINK_ORDER sections and SHF_LINK_ORDER sections with zero sh_link. | |
1652 if (!la || !lb) | |
1653 return la && !lb; | |
1609 OutputSection *aOut = la->getParent(); | 1654 OutputSection *aOut = la->getParent(); |
1610 OutputSection *bOut = lb->getParent(); | 1655 OutputSection *bOut = lb->getParent(); |
1611 | 1656 |
1612 if (aOut != bOut) | 1657 if (aOut != bOut) |
1613 return aOut->addr < bOut->addr; | 1658 return aOut->addr < bOut->addr; |
1614 return la->outSecOff < lb->outSecOff; | 1659 return la->outSecOff < lb->outSecOff; |
1615 } | 1660 } |
1616 | 1661 |
1617 template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { | 1662 template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { |
1663 llvm::TimeTraceScope timeScope("Resolve SHF_LINK_ORDER"); | |
1618 for (OutputSection *sec : outputSections) { | 1664 for (OutputSection *sec : outputSections) { |
1619 if (!(sec->flags & SHF_LINK_ORDER)) | 1665 if (!(sec->flags & SHF_LINK_ORDER)) |
1620 continue; | 1666 continue; |
1621 | 1667 |
1622 // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated | 1668 // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated |
1623 // this processing inside the ARMExidxsyntheticsection::finalizeContents(). | 1669 // this processing inside the ARMExidxsyntheticsection::finalizeContents(). |
1624 if (!config->relocatable && config->emachine == EM_ARM && | 1670 if (!config->relocatable && config->emachine == EM_ARM && |
1625 sec->type == SHT_ARM_EXIDX) | 1671 sec->type == SHT_ARM_EXIDX) |
1626 continue; | 1672 continue; |
1627 | 1673 |
1628 // Link order may be distributed across several InputSectionDescriptions | 1674 // Link order may be distributed across several InputSectionDescriptions. |
1629 // but sort must consider them all at once. | 1675 // Sorting is performed separately. |
1630 std::vector<InputSection **> scriptSections; | 1676 std::vector<InputSection **> scriptSections; |
1631 std::vector<InputSection *> sections; | 1677 std::vector<InputSection *> sections; |
1632 bool started = false, stopped = false; | |
1633 for (BaseCommand *base : sec->sectionCommands) { | 1678 for (BaseCommand *base : sec->sectionCommands) { |
1634 if (auto *isd = dyn_cast<InputSectionDescription>(base)) { | 1679 auto *isd = dyn_cast<InputSectionDescription>(base); |
1635 for (InputSection *&isec : isd->sections) { | 1680 if (!isd) |
1636 if (!(isec->flags & SHF_LINK_ORDER)) { | 1681 continue; |
1637 if (started) | 1682 bool hasLinkOrder = false; |
1638 stopped = true; | 1683 scriptSections.clear(); |
1639 } else if (stopped) { | 1684 sections.clear(); |
1640 error(toString(isec) + ": SHF_LINK_ORDER sections in " + sec->name + | 1685 for (InputSection *&isec : isd->sections) { |
1641 " are not contiguous"); | 1686 if (isec->flags & SHF_LINK_ORDER) { |
1642 } else { | 1687 InputSection *link = isec->getLinkOrderDep(); |
1643 started = true; | 1688 if (link && !link->getParent()) |
1644 | 1689 error(toString(isec) + ": sh_link points to discarded section " + |
1645 scriptSections.push_back(&isec); | 1690 toString(link)); |
1646 sections.push_back(isec); | 1691 hasLinkOrder = true; |
1647 | |
1648 InputSection *link = isec->getLinkOrderDep(); | |
1649 if (!link->getParent()) | |
1650 error(toString(isec) + ": sh_link points to discarded section " + | |
1651 toString(link)); | |
1652 } | |
1653 } | 1692 } |
1654 } else if (started) { | 1693 scriptSections.push_back(&isec); |
1655 stopped = true; | 1694 sections.push_back(isec); |
1656 } | 1695 } |
1657 } | 1696 if (hasLinkOrder && errorCount() == 0) { |
1658 | 1697 llvm::stable_sort(sections, compareByFilePosition); |
1659 if (errorCount()) | 1698 for (int i = 0, n = sections.size(); i != n; ++i) |
1660 continue; | 1699 *scriptSections[i] = sections[i]; |
1661 | 1700 } |
1662 llvm::stable_sort(sections, compareByFilePosition); | 1701 } |
1663 | |
1664 for (int i = 0, n = sections.size(); i < n; ++i) | |
1665 *scriptSections[i] = sections[i]; | |
1666 } | 1702 } |
1667 } | 1703 } |
1668 | 1704 |
1669 static void finalizeSynthetic(SyntheticSection *sec) { | 1705 static void finalizeSynthetic(SyntheticSection *sec) { |
1670 if (sec && sec->isNeeded() && sec->getParent()) | 1706 if (sec && sec->isNeeded() && sec->getParent()) { |
1707 llvm::TimeTraceScope timeScope("Finalize synthetic sections", sec->name); | |
1671 sec->finalizeContents(); | 1708 sec->finalizeContents(); |
1709 } | |
1672 } | 1710 } |
1673 | 1711 |
1674 // We need to generate and finalize the content that depends on the address of | 1712 // We need to generate and finalize the content that depends on the address of |
1675 // InputSections. As the generation of the content may also alter InputSection | 1713 // InputSections. As the generation of the content may also alter InputSection |
1676 // addresses we must converge to a fixed point. We do that here. See the comment | 1714 // addresses we must converge to a fixed point. We do that here. See the comment |
1677 // in Writer<ELFT>::finalizeSections(). | 1715 // in Writer<ELFT>::finalizeSections(). |
1678 template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { | 1716 template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { |
1717 llvm::TimeTraceScope timeScope("Finalize address dependent content"); | |
1679 ThunkCreator tc; | 1718 ThunkCreator tc; |
1680 AArch64Err843419Patcher a64p; | 1719 AArch64Err843419Patcher a64p; |
1681 ARMErr657417Patcher a32p; | 1720 ARMErr657417Patcher a32p; |
1682 script->assignAddresses(); | 1721 script->assignAddresses(); |
1683 // .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they | 1722 // .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they |
1695 int assignPasses = 0; | 1734 int assignPasses = 0; |
1696 for (;;) { | 1735 for (;;) { |
1697 bool changed = target->needsThunks && tc.createThunks(outputSections); | 1736 bool changed = target->needsThunks && tc.createThunks(outputSections); |
1698 | 1737 |
1699 // With Thunk Size much smaller than branch range we expect to | 1738 // With Thunk Size much smaller than branch range we expect to |
1700 // converge quickly; if we get to 10 something has gone wrong. | 1739 // converge quickly; if we get to 15 something has gone wrong. |
1701 if (changed && tc.pass >= 10) { | 1740 if (changed && tc.pass >= 15) { |
1702 error("thunk creation not converged"); | 1741 error("thunk creation not converged"); |
1703 break; | 1742 break; |
1704 } | 1743 } |
1705 | 1744 |
1706 if (config->fixCortexA53Errata843419) { | 1745 if (config->fixCortexA53Errata843419) { |
1746 warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " + | 1785 warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " + |
1747 os->name + " is not a multiple of alignment (" + | 1786 os->name + " is not a multiple of alignment (" + |
1748 Twine(os->alignment) + ")"); | 1787 Twine(os->alignment) + ")"); |
1749 } | 1788 } |
1750 | 1789 |
1751 // If Input Sections have been shrinked (basic block sections) then | 1790 // If Input Sections have been shrunk (basic block sections) then |
1752 // update symbol values and sizes associated with these sections. With basic | 1791 // update symbol values and sizes associated with these sections. With basic |
1753 // block sections, input sections can shrink when the jump instructions at | 1792 // block sections, input sections can shrink when the jump instructions at |
1754 // the end of the section are relaxed. | 1793 // the end of the section are relaxed. |
1755 static void fixSymbolsAfterShrinking() { | 1794 static void fixSymbolsAfterShrinking() { |
1756 for (InputFile *File : objectFiles) { | 1795 for (InputFile *File : objectFiles) { |
1930 /*section=*/nullptr}); | 1969 /*section=*/nullptr}); |
1931 ElfSym::tlsModuleBase = cast<Defined>(s); | 1970 ElfSym::tlsModuleBase = cast<Defined>(s); |
1932 } | 1971 } |
1933 } | 1972 } |
1934 | 1973 |
1935 // This responsible for splitting up .eh_frame section into | 1974 { |
1936 // pieces. The relocation scan uses those pieces, so this has to be | 1975 llvm::TimeTraceScope timeScope("Finalize .eh_frame"); |
1937 // earlier. | 1976 // This responsible for splitting up .eh_frame section into |
1938 for (Partition &part : partitions) | 1977 // pieces. The relocation scan uses those pieces, so this has to be |
1939 finalizeSynthetic(part.ehFrame); | 1978 // earlier. |
1979 for (Partition &part : partitions) | |
1980 finalizeSynthetic(part.ehFrame); | |
1981 } | |
1940 | 1982 |
1941 for (Symbol *sym : symtab->symbols()) | 1983 for (Symbol *sym : symtab->symbols()) |
1942 sym->isPreemptible = computeIsPreemptible(*sym); | 1984 sym->isPreemptible = computeIsPreemptible(*sym); |
1943 | 1985 |
1944 // Change values of linker-script-defined symbols from placeholders (assigned | 1986 // Change values of linker-script-defined symbols from placeholders (assigned |
1945 // by declareSymbols) to actual definitions. | 1987 // by declareSymbols) to actual definitions. |
1946 script->processSymbolAssignments(); | 1988 script->processSymbolAssignments(); |
1947 | 1989 |
1948 // Scan relocations. This must be done after every symbol is declared so that | 1990 { |
1949 // we can correctly decide if a dynamic relocation is needed. This is called | 1991 llvm::TimeTraceScope timeScope("Scan relocations"); |
1950 // after processSymbolAssignments() because it needs to know whether a | 1992 // Scan relocations. This must be done after every symbol is declared so |
1951 // linker-script-defined symbol is absolute. | 1993 // that we can correctly decide if a dynamic relocation is needed. This is |
1952 ppc64noTocRelax.clear(); | 1994 // called after processSymbolAssignments() because it needs to know whether |
1953 if (!config->relocatable) { | 1995 // a linker-script-defined symbol is absolute. |
1954 forEachRelSec(scanRelocations<ELFT>); | 1996 ppc64noTocRelax.clear(); |
1955 reportUndefinedSymbols<ELFT>(); | 1997 if (!config->relocatable) { |
1998 forEachRelSec(scanRelocations<ELFT>); | |
1999 reportUndefinedSymbols<ELFT>(); | |
2000 } | |
1956 } | 2001 } |
1957 | 2002 |
1958 if (in.plt && in.plt->isNeeded()) | 2003 if (in.plt && in.plt->isNeeded()) |
1959 in.plt->addSymbols(); | 2004 in.plt->addSymbols(); |
1960 if (in.iplt && in.iplt->isNeeded()) | 2005 if (in.iplt && in.iplt->isNeeded()) |
1961 in.iplt->addSymbols(); | 2006 in.iplt->addSymbols(); |
1962 | 2007 |
1963 if (!config->allowShlibUndefined) { | 2008 if (config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) { |
2009 auto diagnose = | |
2010 config->unresolvedSymbolsInShlib == UnresolvedPolicy::ReportError | |
2011 ? errorOrWarn | |
2012 : warn; | |
1964 // Error on undefined symbols in a shared object, if all of its DT_NEEDED | 2013 // Error on undefined symbols in a shared object, if all of its DT_NEEDED |
1965 // entries are seen. These cases would otherwise lead to runtime errors | 2014 // entries are seen. These cases would otherwise lead to runtime errors |
1966 // reported by the dynamic linker. | 2015 // reported by the dynamic linker. |
1967 // | 2016 // |
1968 // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to | 2017 // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to |
1969 // catch more cases. That is too much for us. Our approach resembles the one | 2018 // catch more cases. That is too much for us. Our approach resembles the one |
1970 // used in ld.gold, achieves a good balance to be useful but not too smart. | 2019 // used in ld.gold, achieves a good balance to be useful but not too smart. |
1971 for (SharedFile *file : sharedFiles) | 2020 for (SharedFile *file : sharedFiles) { |
1972 file->allNeededIsKnown = | 2021 bool allNeededIsKnown = |
1973 llvm::all_of(file->dtNeeded, [&](StringRef needed) { | 2022 llvm::all_of(file->dtNeeded, [&](StringRef needed) { |
1974 return symtab->soNames.count(needed); | 2023 return symtab->soNames.count(needed); |
1975 }); | 2024 }); |
1976 | 2025 if (!allNeededIsKnown) |
1977 for (Symbol *sym : symtab->symbols()) | 2026 continue; |
1978 if (sym->isUndefined() && !sym->isWeak()) | 2027 for (Symbol *sym : file->requiredSymbols) |
1979 if (auto *f = dyn_cast_or_null<SharedFile>(sym->file)) | 2028 if (sym->isUndefined() && !sym->isWeak()) |
1980 if (f->allNeededIsKnown) | 2029 diagnose(toString(file) + ": undefined reference to " + |
1981 error(toString(f) + ": undefined reference to " + toString(*sym)); | 2030 toString(*sym) + " [--no-allow-shlib-undefined]"); |
1982 } | 2031 } |
1983 | 2032 } |
1984 // Now that we have defined all possible global symbols including linker- | 2033 |
1985 // synthesized ones. Visit all symbols to give the finishing touches. | 2034 { |
1986 for (Symbol *sym : symtab->symbols()) { | 2035 llvm::TimeTraceScope timeScope("Add symbols to symtabs"); |
1987 if (!includeInSymtab(*sym)) | 2036 // Now that we have defined all possible global symbols including linker- |
1988 continue; | 2037 // synthesized ones. Visit all symbols to give the finishing touches. |
1989 if (in.symTab) | 2038 for (Symbol *sym : symtab->symbols()) { |
1990 in.symTab->addSymbol(sym); | 2039 if (!includeInSymtab(*sym)) |
1991 | 2040 continue; |
1992 if (sym->includeInDynsym()) { | 2041 if (in.symTab) |
1993 partitions[sym->partition - 1].dynSymTab->addSymbol(sym); | 2042 in.symTab->addSymbol(sym); |
1994 if (auto *file = dyn_cast_or_null<SharedFile>(sym->file)) | 2043 |
1995 if (file->isNeeded && !sym->isUndefined()) | 2044 if (sym->includeInDynsym()) { |
1996 addVerneed(sym); | 2045 partitions[sym->partition - 1].dynSymTab->addSymbol(sym); |
1997 } | 2046 if (auto *file = dyn_cast_or_null<SharedFile>(sym->file)) |
1998 } | 2047 if (file->isNeeded && !sym->isUndefined()) |
1999 | 2048 addVerneed(sym); |
2000 // We also need to scan the dynamic relocation tables of the other partitions | 2049 } |
2001 // and add any referenced symbols to the partition's dynsym. | 2050 } |
2002 for (Partition &part : MutableArrayRef<Partition>(partitions).slice(1)) { | 2051 |
2003 DenseSet<Symbol *> syms; | 2052 // We also need to scan the dynamic relocation tables of the other |
2004 for (const SymbolTableEntry &e : part.dynSymTab->getSymbols()) | 2053 // partitions and add any referenced symbols to the partition's dynsym. |
2005 syms.insert(e.sym); | 2054 for (Partition &part : MutableArrayRef<Partition>(partitions).slice(1)) { |
2006 for (DynamicReloc &reloc : part.relaDyn->relocs) | 2055 DenseSet<Symbol *> syms; |
2007 if (reloc.sym && !reloc.useSymVA && syms.insert(reloc.sym).second) | 2056 for (const SymbolTableEntry &e : part.dynSymTab->getSymbols()) |
2008 part.dynSymTab->addSymbol(reloc.sym); | 2057 syms.insert(e.sym); |
2058 for (DynamicReloc &reloc : part.relaDyn->relocs) | |
2059 if (reloc.sym && !reloc.useSymVA && syms.insert(reloc.sym).second) | |
2060 part.dynSymTab->addSymbol(reloc.sym); | |
2061 } | |
2009 } | 2062 } |
2010 | 2063 |
2011 // Do not proceed if there was an undefined symbol. | 2064 // Do not proceed if there was an undefined symbol. |
2012 if (errorCount()) | 2065 if (errorCount()) |
2013 return; | 2066 return; |
2084 | 2137 |
2085 // Some symbols are defined in term of program headers. Now that we | 2138 // Some symbols are defined in term of program headers. Now that we |
2086 // have the headers, we can find out which sections they point to. | 2139 // have the headers, we can find out which sections they point to. |
2087 setReservedSymbolSections(); | 2140 setReservedSymbolSections(); |
2088 | 2141 |
2089 finalizeSynthetic(in.bss); | 2142 { |
2090 finalizeSynthetic(in.bssRelRo); | 2143 llvm::TimeTraceScope timeScope("Finalize synthetic sections"); |
2091 finalizeSynthetic(in.symTabShndx); | 2144 |
2092 finalizeSynthetic(in.shStrTab); | 2145 finalizeSynthetic(in.bss); |
2093 finalizeSynthetic(in.strTab); | 2146 finalizeSynthetic(in.bssRelRo); |
2094 finalizeSynthetic(in.got); | 2147 finalizeSynthetic(in.symTabShndx); |
2095 finalizeSynthetic(in.mipsGot); | 2148 finalizeSynthetic(in.shStrTab); |
2096 finalizeSynthetic(in.igotPlt); | 2149 finalizeSynthetic(in.strTab); |
2097 finalizeSynthetic(in.gotPlt); | 2150 finalizeSynthetic(in.got); |
2098 finalizeSynthetic(in.relaIplt); | 2151 finalizeSynthetic(in.mipsGot); |
2099 finalizeSynthetic(in.relaPlt); | 2152 finalizeSynthetic(in.igotPlt); |
2100 finalizeSynthetic(in.plt); | 2153 finalizeSynthetic(in.gotPlt); |
2101 finalizeSynthetic(in.iplt); | 2154 finalizeSynthetic(in.relaIplt); |
2102 finalizeSynthetic(in.ppc32Got2); | 2155 finalizeSynthetic(in.relaPlt); |
2103 finalizeSynthetic(in.partIndex); | 2156 finalizeSynthetic(in.plt); |
2104 | 2157 finalizeSynthetic(in.iplt); |
2105 // Dynamic section must be the last one in this list and dynamic | 2158 finalizeSynthetic(in.ppc32Got2); |
2106 // symbol table section (dynSymTab) must be the first one. | 2159 finalizeSynthetic(in.partIndex); |
2107 for (Partition &part : partitions) { | 2160 |
2108 finalizeSynthetic(part.dynSymTab); | 2161 // Dynamic section must be the last one in this list and dynamic |
2109 finalizeSynthetic(part.gnuHashTab); | 2162 // symbol table section (dynSymTab) must be the first one. |
2110 finalizeSynthetic(part.hashTab); | 2163 for (Partition &part : partitions) { |
2111 finalizeSynthetic(part.verDef); | 2164 finalizeSynthetic(part.dynSymTab); |
2112 finalizeSynthetic(part.relaDyn); | 2165 finalizeSynthetic(part.gnuHashTab); |
2113 finalizeSynthetic(part.relrDyn); | 2166 finalizeSynthetic(part.hashTab); |
2114 finalizeSynthetic(part.ehFrameHdr); | 2167 finalizeSynthetic(part.verDef); |
2115 finalizeSynthetic(part.verSym); | 2168 finalizeSynthetic(part.relaDyn); |
2116 finalizeSynthetic(part.verNeed); | 2169 finalizeSynthetic(part.relrDyn); |
2117 finalizeSynthetic(part.dynamic); | 2170 finalizeSynthetic(part.ehFrameHdr); |
2171 finalizeSynthetic(part.verSym); | |
2172 finalizeSynthetic(part.verNeed); | |
2173 finalizeSynthetic(part.dynamic); | |
2174 } | |
2118 } | 2175 } |
2119 | 2176 |
2120 if (!script->hasSectionsCommand && !config->relocatable) | 2177 if (!script->hasSectionsCommand && !config->relocatable) |
2121 fixSectionAlignments(); | 2178 fixSectionAlignments(); |
2122 | 2179 |
2143 // values. They also might change after adding the thunks. | 2200 // values. They also might change after adding the thunks. |
2144 finalizeAddressDependentContent(); | 2201 finalizeAddressDependentContent(); |
2145 if (errorCount()) | 2202 if (errorCount()) |
2146 return; | 2203 return; |
2147 | 2204 |
2148 // finalizeAddressDependentContent may have added local symbols to the static symbol table. | 2205 { |
2149 finalizeSynthetic(in.symTab); | 2206 llvm::TimeTraceScope timeScope("Finalize synthetic sections"); |
2150 finalizeSynthetic(in.ppc64LongBranchTarget); | 2207 // finalizeAddressDependentContent may have added local symbols to the |
2208 // static symbol table. | |
2209 finalizeSynthetic(in.symTab); | |
2210 finalizeSynthetic(in.ppc64LongBranchTarget); | |
2211 } | |
2151 | 2212 |
2152 // Relaxation to delete inter-basic block jumps created by basic block | 2213 // Relaxation to delete inter-basic block jumps created by basic block |
2153 // sections. Run after in.symTab is finalized as optimizeBasicBlockJumps | 2214 // sections. Run after in.symTab is finalized as optimizeBasicBlockJumps |
2154 // can relax jump instructions based on symbol offset. | 2215 // can relax jump instructions based on symbol offset. |
2155 if (config->optimizeBBJumps) | 2216 if (config->optimizeBBJumps) |
2226 template <class ELFT> | 2287 template <class ELFT> |
2227 void Writer<ELFT>::addStartStopSymbols(OutputSection *sec) { | 2288 void Writer<ELFT>::addStartStopSymbols(OutputSection *sec) { |
2228 StringRef s = sec->name; | 2289 StringRef s = sec->name; |
2229 if (!isValidCIdentifier(s)) | 2290 if (!isValidCIdentifier(s)) |
2230 return; | 2291 return; |
2231 addOptionalRegular(saver.save("__start_" + s), sec, 0, STV_PROTECTED); | 2292 addOptionalRegular(saver.save("__start_" + s), sec, 0, |
2232 addOptionalRegular(saver.save("__stop_" + s), sec, -1, STV_PROTECTED); | 2293 config->zStartStopVisibility); |
2294 addOptionalRegular(saver.save("__stop_" + s), sec, -1, | |
2295 config->zStartStopVisibility); | |
2233 } | 2296 } |
2234 | 2297 |
2235 static bool needsPtLoad(OutputSection *sec) { | 2298 static bool needsPtLoad(OutputSection *sec) { |
2236 if (!(sec->flags & SHF_ALLOC) || sec->noload) | 2299 if (!(sec->flags & SHF_ALLOC) || sec->noload) |
2237 return false; | 2300 return false; |
2321 relroEnd = sec; | 2384 relroEnd = sec; |
2322 } | 2385 } |
2323 } | 2386 } |
2324 | 2387 |
2325 for (OutputSection *sec : outputSections) { | 2388 for (OutputSection *sec : outputSections) { |
2326 if (!(sec->flags & SHF_ALLOC)) | |
2327 break; | |
2328 if (!needsPtLoad(sec)) | 2389 if (!needsPtLoad(sec)) |
2329 continue; | 2390 continue; |
2330 | 2391 |
2331 // Normally, sections in partitions other than the current partition are | 2392 // Normally, sections in partitions other than the current partition are |
2332 // ignored. But partition number 255 is a special case: it contains the | 2393 // ignored. But partition number 255 is a special case: it contains the |
2542 return off; | 2603 return off; |
2543 return off + os->size; | 2604 return off + os->size; |
2544 } | 2605 } |
2545 | 2606 |
2546 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { | 2607 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { |
2547 uint64_t off = 0; | 2608 // Compute the minimum LMA of all non-empty non-NOBITS sections as minAddr. |
2609 auto needsOffset = [](OutputSection &sec) { | |
2610 return sec.type != SHT_NOBITS && (sec.flags & SHF_ALLOC) && sec.size > 0; | |
2611 }; | |
2612 uint64_t minAddr = UINT64_MAX; | |
2548 for (OutputSection *sec : outputSections) | 2613 for (OutputSection *sec : outputSections) |
2549 if (sec->flags & SHF_ALLOC) | 2614 if (needsOffset(*sec)) { |
2550 off = setFileOffset(sec, off); | 2615 sec->offset = sec->getLMA(); |
2551 fileSize = alignTo(off, config->wordsize); | 2616 minAddr = std::min(minAddr, sec->offset); |
2617 } | |
2618 | |
2619 // Sections are laid out at LMA minus minAddr. | |
2620 fileSize = 0; | |
2621 for (OutputSection *sec : outputSections) | |
2622 if (needsOffset(*sec)) { | |
2623 sec->offset -= minAddr; | |
2624 fileSize = std::max(fileSize, sec->offset + sec->size); | |
2625 } | |
2552 } | 2626 } |
2553 | 2627 |
2554 static std::string rangeToString(uint64_t addr, uint64_t len) { | 2628 static std::string rangeToString(uint64_t addr, uint64_t len) { |
2555 return "[0x" + utohexstr(addr) + ", 0x" + utohexstr(addr + len - 1) + "]"; | 2629 return "[0x" + utohexstr(addr) + ", 0x" + utohexstr(addr + len - 1) + "]"; |
2556 } | 2630 } |
2565 for (Partition &part : partitions) | 2639 for (Partition &part : partitions) |
2566 for (PhdrEntry *p : part.phdrs) | 2640 for (PhdrEntry *p : part.phdrs) |
2567 if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) | 2641 if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) |
2568 lastRX = p; | 2642 lastRX = p; |
2569 | 2643 |
2644 // Layout SHF_ALLOC sections before non-SHF_ALLOC sections. A non-SHF_ALLOC | |
2645 // will not occupy file offsets contained by a PT_LOAD. | |
2570 for (OutputSection *sec : outputSections) { | 2646 for (OutputSection *sec : outputSections) { |
2647 if (!(sec->flags & SHF_ALLOC)) | |
2648 continue; | |
2571 off = setFileOffset(sec, off); | 2649 off = setFileOffset(sec, off); |
2572 | 2650 |
2573 // If this is a last section of the last executable segment and that | 2651 // If this is a last section of the last executable segment and that |
2574 // segment is the last loadable segment, align the offset of the | 2652 // segment is the last loadable segment, align the offset of the |
2575 // following section to avoid loading non-segments parts of the file. | 2653 // following section to avoid loading non-segments parts of the file. |
2576 if (config->zSeparate != SeparateSegmentKind::None && lastRX && | 2654 if (config->zSeparate != SeparateSegmentKind::None && lastRX && |
2577 lastRX->lastSec == sec) | 2655 lastRX->lastSec == sec) |
2578 off = alignTo(off, config->commonPageSize); | 2656 off = alignTo(off, config->commonPageSize); |
2579 } | 2657 } |
2658 for (OutputSection *sec : outputSections) | |
2659 if (!(sec->flags & SHF_ALLOC)) | |
2660 off = setFileOffset(sec, off); | |
2580 | 2661 |
2581 sectionHeaderOff = alignTo(off, config->wordsize); | 2662 sectionHeaderOff = alignTo(off, config->wordsize); |
2582 fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr); | 2663 fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr); |
2583 | 2664 |
2584 // Our logic assumes that sections have rising VA within the same segment. | 2665 // Our logic assumes that sections have rising VA within the same segment. |
2806 | 2887 |
2807 // Open a result file. | 2888 // Open a result file. |
2808 template <class ELFT> void Writer<ELFT>::openFile() { | 2889 template <class ELFT> void Writer<ELFT>::openFile() { |
2809 uint64_t maxSize = config->is64 ? INT64_MAX : UINT32_MAX; | 2890 uint64_t maxSize = config->is64 ? INT64_MAX : UINT32_MAX; |
2810 if (fileSize != size_t(fileSize) || maxSize < fileSize) { | 2891 if (fileSize != size_t(fileSize) || maxSize < fileSize) { |
2811 error("output file too large: " + Twine(fileSize) + " bytes"); | 2892 std::string msg; |
2893 raw_string_ostream s(msg); | |
2894 s << "output file too large: " << Twine(fileSize) << " bytes\n" | |
2895 << "section sizes:\n"; | |
2896 for (OutputSection *os : outputSections) | |
2897 s << os->name << ' ' << os->size << "\n"; | |
2898 error(s.str()); | |
2812 return; | 2899 return; |
2813 } | 2900 } |
2814 | 2901 |
2815 unlinkAsync(config->outputFile); | 2902 unlinkAsync(config->outputFile); |
2816 unsigned flags = 0; | 2903 unsigned flags = 0; |
2881 sec->writeTo<ELFT>(Out::bufferStart + sec->offset); | 2968 sec->writeTo<ELFT>(Out::bufferStart + sec->offset); |
2882 | 2969 |
2883 for (OutputSection *sec : outputSections) | 2970 for (OutputSection *sec : outputSections) |
2884 if (sec->type != SHT_REL && sec->type != SHT_RELA) | 2971 if (sec->type != SHT_REL && sec->type != SHT_RELA) |
2885 sec->writeTo<ELFT>(Out::bufferStart + sec->offset); | 2972 sec->writeTo<ELFT>(Out::bufferStart + sec->offset); |
2886 } | |
2887 | |
2888 // Split one uint8 array into small pieces of uint8 arrays. | |
2889 static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> arr, | |
2890 size_t chunkSize) { | |
2891 std::vector<ArrayRef<uint8_t>> ret; | |
2892 while (arr.size() > chunkSize) { | |
2893 ret.push_back(arr.take_front(chunkSize)); | |
2894 arr = arr.drop_front(chunkSize); | |
2895 } | |
2896 if (!arr.empty()) | |
2897 ret.push_back(arr); | |
2898 return ret; | |
2899 } | 2973 } |
2900 | 2974 |
2901 // Computes a hash value of Data using a given hash function. | 2975 // Computes a hash value of Data using a given hash function. |
2902 // In order to utilize multiple cores, we first split data into 1MB | 2976 // In order to utilize multiple cores, we first split data into 1MB |
2903 // chunks, compute a hash for each chunk, and then compute a hash value | 2977 // chunks, compute a hash for each chunk, and then compute a hash value |