LLVM: lib/ObjCopy/ELF/ELFObject.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
22#include
23#include
24#include
25#include
26#include <unordered_set>
27#include
28#include
29
30using namespace llvm;
35
37 uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
38 Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);
39 Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
40 Phdr.p_type = Seg.Type;
41 Phdr.p_flags = Seg.Flags;
42 Phdr.p_offset = Seg.Offset;
43 Phdr.p_vaddr = Seg.VAddr;
44 Phdr.p_paddr = Seg.PAddr;
46 Phdr.p_memsz = Seg.MemSize;
47 Phdr.p_align = Seg.Align;
48}
49
53}
54
57}
58
65
69 Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
80}
81
84}
85
88}
89
92}
93
94template
97}
98
99template
103
104 Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
106}
107
108template
110 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
113 ELF::encodeCrel(OS, Relocations, [&](const Relocation &R) {
114 uint32_t CurSymIdx = R.RelocSymbol ? R.RelocSymbol->Index : 0;
115 return ELF::Elf_Crel{static_cast<uint>(R.Offset), CurSymIdx, R.Type,
116 std::make_signed_t(R.Addend)};
117 });
119}
120
121template
124 Sec.Size = encodeCrelELFT::Is64Bits(Sec.Relocations).size();
125 } else {
127 Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
128
129 Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
130 }
132}
133
134template
137}
138
140 Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);
142}
143
144template
147}
148
151}
152
153template
156}
157
160 "cannot write symbol section index table '" +
161 Sec.Name + "' ");
162}
163
166 "cannot write symbol table '" + Sec.Name +
167 "' out to binary");
168}
169
172 "cannot write relocation section '" + Sec.Name +
173 "' out to binary");
174}
175
178 "cannot write '" + Sec.Name + "' out to binary");
179}
180
183 "cannot write '" + Sec.Name + "' out to binary");
184}
192
194
195 return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
196}
197
204}
205
206
207
208template <class T, class Iterator>
209static Iterator toHexStr(T X, Iterator It, size_t Len) {
210
211 std::fill(It, It + Len, '0');
212
213 for (long I = Len - 1; I >= 0; --I) {
214 unsigned char Mod = static_cast<unsigned char>(X) & 15;
215 *(It + I) = hexdigit(Mod, false);
216 X >>= 4;
217 }
219 return It + Len;
220}
221
225 while (!S.empty()) {
226 Checksum += checkedGetHex<uint8_t>(S.take_front(2));
228 }
229 return -Checksum;
230}
231
236 auto Iter = Line.begin();
237 *Iter++ = ':';
243 StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
245 *Iter++ = '\r';
246 *Iter++ = '\n';
247 assert(Iter == Line.end());
248 return Line;
249}
250
252 switch (R.Type) {
254 if (R.HexData.size() == 0)
257 "zero data length is not allowed for data records");
258 break;
260 break;
262
263
264 if (R.HexData.size() != 4)
267 "segment address data should be 2 bytes in size");
268 break;
271 if (R.HexData.size() != 8)
273 "start address data should be 4 bytes in size");
274
275
276
277
279 R.HexData.take_front(3) != "000")
281 "start address exceeds 20 bit for 80x86");
282 break;
284
285 if (R.HexData.size() != 4)
288 "extended address data should be 2 bytes in size");
289 break;
290 default:
291
293 static_cast<unsigned>(R.Type));
294 }
296}
297
298
299
300
302 assert(!Line.empty());
303 if (Line[0] != ':')
305 "missing ':' in the beginning of line.");
306
307 for (size_t Pos = 1; Pos < Line.size(); ++Pos)
308 if (hexDigitValue(Line[Pos]) == -1U)
310 "invalid character at position %zu.", Pos + 1);
312}
313
315 assert(!Line.empty());
316
317
318 if (Line.size() < 11)
320 "line is too short: %zu chars.", Line.size());
321
323 return std::move(E);
324
326 size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
327 if (Line.size() != getLength(DataLen))
329 "invalid line length %zu (should be %zu)",
330 Line.size(), getLength(DataLen));
331
332 Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
333 Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
334 Rec.HexData = Line.substr(9, DataLen * 2);
335
336 if (getChecksum(Line.drop_front(1)) != 0)
339 return std::move(E);
340 return Rec;
341}
342
346 Seg = nullptr;
349}
350
354 const uint32_t ChunkSize = 16;
356 while (.empty()) {
357 uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
358 if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
359 if (Addr > 0xFFFFFU) {
360
361
362 if (SegmentAddr != 0)
363 SegmentAddr = writeSegmentAddr(0U);
364 BaseAddr = writeBaseAddr(Addr);
365 } else {
366
367 SegmentAddr = writeSegmentAddr(Addr);
368 }
369 }
370 uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
371 assert(SegOffset <= 0xFFFFU);
372 DataSize = std::min(DataSize, 0x10000U - SegOffset);
373 writeData(0, SegOffset, Data.take_front(DataSize));
374 Addr += DataSize;
375 Data = Data.drop_front(DataSize);
376 }
377}
378
383 return Addr & 0xF0000U;
384}
385
390 static_cast<uint8_t>((Base >> 16) & 0xFF)};
393}
394
398}
399
403}
404
408}
409
411
413
414
415
416 writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});
418}
419
423}
424
430}
431
434 std::vector<uint8_t> Data(Sec.Size);
435 Sec.StrTabBuilder.write(Data.data());
438}
439
441 return Visitor.visit(*this);
442}
443
445 return Visitor.visit(*this);
446}
447
449 if (HasSymTabLink) {
450 assert(LinkSection == nullptr);
451 LinkSection = &SymTab;
452 }
453}
454
458}
459
460template
466 switch (Sec.ChType) {
469 break;
472 break;
473 default:
475 "--decompress-debug-sections: ch_type (" +
477 Sec.Name + "' is unsupported");
478 }
479 if (auto *Reason =
482 "failed to decompress section '" + Sec.Name +
483 "': " + Reason);
485 static_cast<size_t>(Sec.Size)))
487 "failed to decompress section '" + Sec.Name +
488 "': " + toString(std::move(E)));
489
490 uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
491 std::copy(Decompressed.begin(), Decompressed.end(), Buf);
492
494}
495
498 "cannot write compressed section '" + Sec.Name +
499 "' ");
500}
501
503 return Visitor.visit(*this);
504}
505
507 return Visitor.visit(*this);
508}
509
511 return Visitor.visit(*this);
512}
513
515 return Visitor.visit(*this);
516}
517
520 while (!HexData.empty()) {
521 Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));
523 }
524 Size = Data.size();
525}
526
529 "cannot write compressed section '" + Sec.Name +
530 "' ");
531}
532
533template
535 uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
537 switch (Sec.CompressionType) {
543 break;
546 break;
547 }
548 Chdr.ch_size = Sec.DecompressedSize;
549 Chdr.ch_addralign = Sec.DecompressedAlign;
550 memcpy(Buf, &Chdr, sizeof(Chdr));
551 Buf += sizeof(Chdr);
552
553 std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
555}
556
559 bool Is64Bits)
560 : SectionBase(Sec), CompressionType(CompressionType),
561 DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
563 CompressedData);
564
569 Size = ChdrSize + CompressedData.size();
571}
572
577 DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
579}
580
582 return Visitor.visit(*this);
583}
584
586 return Visitor.visit(*this);
587}
588
590
593}
594
598}
599
604}
605
607 return Visitor.visit(*this);
608}
609
611 return Visitor.visit(*this);
612}
613
614template
616 uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
617 llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
619}
620
626 "Link field value " + Twine(Link) + " in section " + Name +
627 " is invalid",
628 "Link field value " + Twine(Link) + " in section " + Name +
629 " is not a symbol table");
630 if (!Sec)
632
636}
637
639
641 return Visitor.visit(*this);
642}
643
645 return Visitor.visit(*this);
646}
647
649 switch (Index) {
652 return true;
653 }
654
657 }
658
660 switch (Index) {
664 return true;
665 }
666 }
667
669 switch (Index) {
675 return true;
676 }
677 }
678 return false;
679}
680
681
682
683
689 }
690
692
693
695 }
696
701}
702
704
705void SymbolTableSection::assignIndices() {
711 }
712}
713
720 Sym.Binding = Bind;
722 Sym.DefinedIn = DefinedIn;
723 if (DefinedIn != nullptr)
725 if (DefinedIn == nullptr) {
728 else
730 }
732 Sym.Visibility = Visibility;
733 Sym.Size = SymbolSize;
735 Symbols.emplace_back(std::make_unique(Sym));
737}
738
744 if (!AllowBrokenLinks)
747 "string table '%s' cannot be removed because it is "
748 "referenced by the symbol table '%s'",
751 }
754}
755
758 Callable(*Sym);
759 std::stable_partition(
762 assignIndices();
763}
764
768 std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
771 auto PrevSize = Size;
773 if (Size < PrevSize)
775 assignIndices();
777}
778
781 for (std::unique_ptr &Sym : Symbols)
783 Sym->DefinedIn = To;
784}
785
791 "Symbol table has link index of " + Twine(Link) +
792 " which is not a valid index",
793 "Symbol table has link index of " + Twine(Link) +
794 " which is not a string table");
795 if (!Sec)
797
798 setStrTab(*Sec);
800}
801
804 for (std::unique_ptr &Sym : Symbols) {
805 Sym->NameIndex =
808 MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
809 }
810
812 Info = MaxLocalIndex + 1;
813}
814
816
817
818
821
822
823
824
825
827 for (std::unique_ptr &Sym : Symbols)
829}
830
833 return;
834
835
836 for (const std::unique_ptr &Sym : Symbols) {
839 else
841 }
842}
843
848 "invalid symbol index: " + Twine(Index));
850}
851
855 if ()
856 return Sym.takeError();
857
858 return const_cast<Symbol *>(*Sym);
859}
860
861template
863 Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);
864
865 for (const std::unique_ptr &Symbol : Sec.Symbols) {
874 }
876}
877
879 return Visitor.visit(*this);
880}
881
883 return Visitor.visit(*this);
884}
885
887 switch (Type) {
889 return ".rel";
891 return ".rela";
893 return ".crel";
894 default:
896 }
897}
898
902 if (!AllowBrokenLinks)
905 "symbol table '%s' cannot be removed because it is "
906 "referenced by the relocation section '%s'",
907 Symbols->Name.data(), this->Name.data());
909 }
910
911 for (const Relocation &R : Relocations) {
912 if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
913 (R.RelocSymbol->DefinedIn))
914 continue;
916 "section '%s' cannot be removed: (%s+0x%" PRIx64
917 ") has relocation against symbol '%s'",
918 R.RelocSymbol->DefinedIn->Name.data(),
920 R.RelocSymbol->Name.c_str());
921 }
922
924}
925
926template
931 Link,
932 "Link field value " + Twine(Link) + " in section " + Name +
933 " is invalid",
934 "Link field value " + Twine(Link) + " in section " + Name +
935 " is not a symbol table");
936 if (!Sec)
938
939 setSymTab(*Sec);
940 }
941
945 " in section " + Name + " is invalid");
946 if (!Sec)
948
949 setSection(*Sec);
950 } else
951 setSection(nullptr);
952
954}
955
956template
958 this->Link = Symbols ? Symbols->Index : 0;
959
960 if (SecToApplyRel != nullptr)
961 this->Info = SecToApplyRel->Index;
962}
963
964template
966
967template
969 Rela.r_addend = Addend;
970}
971
972template <class RelRange, class T>
973static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {
974 for (const auto &Reloc : Relocations) {
975 Buf->r_offset = Reloc.Offset;
977 Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
978 Reloc.Type, IsMips64EL);
979 ++Buf;
980 }
981}
982
983template
985 uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
987 auto Content = encodeCrelELFT::Is64Bits(Sec.Relocations);
990 writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),
992 } else {
993 writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),
995 }
997}
998
1000 return Visitor.visit(*this);
1001}
1002
1004 return Visitor.visit(*this);
1005}
1006
1009 for (const Relocation &Reloc : Relocations)
1010 if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))
1013 "not stripping symbol '%s' because it is named in a relocation",
1014 Reloc.RelocSymbol->Name.data());
1016}
1017
1019 for (const Relocation &Reloc : Relocations)
1020 if (Reloc.RelocSymbol)
1021 Reloc.RelocSymbol->Referenced = true;
1022}
1023
1026
1029}
1030
1034}
1035
1037 return Visitor.visit(*this);
1038}
1039
1041 return Visitor.visit(*this);
1042}
1043
1047 if (!AllowBrokenLinks)
1050 "symbol table '%s' cannot be removed because it is "
1051 "referenced by the relocation section '%s'",
1052 Symbols->Name.data(), this->Name.data());
1054 }
1055
1056
1057
1058
1059
1062}
1063
1065 bool AllowBrokenDependency,
1067 if (ToRemove(LinkSection)) {
1068 if (!AllowBrokenDependency)
1070 "section '%s' cannot be removed because it is "
1071 "referenced by the section '%s'",
1072 LinkSection->Name.data(), this->Name.data());
1073 LinkSection = nullptr;
1074 }
1076}
1077
1079 this->Info = Sym ? Sym->Index : 0;
1080 this->Link = SymTab ? SymTab->Index : 0;
1081
1082
1083
1084
1086 this->FlagWord &= ~GRP_COMDAT;
1087}
1088
1092 if (!AllowBrokenLinks)
1095 "section '.symtab' cannot be removed because it is "
1096 "referenced by the group section '%s'",
1097 this->Name.data());
1098 SymTab = nullptr;
1099 Sym = nullptr;
1100 }
1103}
1104
1108 "symbol '%s' cannot be removed because it is "
1109 "referenced by the section '%s[%d]'",
1110 Sym->Name.data(), this->Name.data(), this->Index);
1112}
1113
1115 if (Sym)
1117}
1118
1123 Sec = To;
1124}
1125
1127
1128
1130 Sec->Flags &= ~SHF_GROUP;
1131}
1132
1136
1139 " in section " + Name + " is invalid");
1140 if (!Sec)
1142
1143 LinkSection = *Sec;
1144
1146 HasSymTabLink = true;
1147 LinkSection = nullptr;
1148 }
1149
1151}
1152
1154
1157
1158
1159
1160
1162
1165 Name = ".gnu_debuglink";
1166
1167
1168
1169 OriginalOffset = std::numeric_limits<uint64_t>::max();
1170}
1171
1174 : FileName(File), CRC32(PrecomputedCRC) {
1176}
1177
1178template
1180 unsigned char *Buf =
1181 reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
1182 Elf_Word *CRC =
1183 reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
1184 *CRC = Sec.CRC32;
1187}
1188
1190 return Visitor.visit(*this);
1191}
1192
1194 return Visitor.visit(*this);
1195}
1196
1197template
1201 endian::write32ELFT::Endianness(Buf++, Sec.FlagWord);
1203 endian::write32ELFT::Endianness(Buf++, S->Index);
1205}
1206
1208 return Visitor.visit(*this);
1209}
1210
1212 return Visitor.visit(*this);
1213}
1214
1215
1217
1218
1219
1220
1222
1223
1224 if (Sec.OriginalOffset == std::numeric_limits<uint64_t>::max())
1225 return false;
1226
1229 return false;
1230
1232 bool SegmentIsTLS = Seg.Type == PT_TLS;
1233 if (SectionIsTLS != SegmentIsTLS)
1234 return false;
1235
1238 }
1239
1242}
1243
1244
1245
1247 const Segment &Parent) {
1248
1251}
1252
1254
1255
1256 if (A->OriginalOffset < B->OriginalOffset)
1257 return true;
1258 if (A->OriginalOffset > B->OriginalOffset)
1259 return false;
1260
1261
1262
1263
1264 if (A->Align != B->Align)
1265 return A->Align > B->Align;
1266 return A->Index < B->Index;
1267}
1268
1270 Obj->Flags = 0x0;
1273 Obj->ABIVersion = 0;
1274 Obj->Entry = 0x0;
1276 Obj->Version = 1;
1277}
1278
1280
1283 StrTab.Name = ".strtab";
1284
1285 Obj->SectionNames = &StrTab;
1286 return &StrTab;
1287}
1288
1291
1292 SymTab.Name = ".symtab";
1293 SymTab.Link = StrTab->Index;
1294
1295
1296 SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
1297
1298 Obj->SymbolTable = &SymTab;
1299 return &SymTab;
1300}
1301
1305 return Err;
1306
1308}
1309
1315 DataSection.Name = ".data";
1317 DataSection.Size = Data.size();
1319
1321 std::replace_if(
1322 std::begin(SanitizedFilename), std::end(SanitizedFilename),
1323 [](char C) { return !isAlnum(C); }, '_');
1324 Twine Prefix = Twine("_binary_") + SanitizedFilename;
1325
1327 0, NewSymbolVisibility, 0, 0);
1329 DataSection.Size, NewSymbolVisibility, 0, 0);
1331 DataSection.Size, NewSymbolVisibility, SHN_ABS,
1332 0);
1333}
1334
1338
1341 return std::move(Err);
1342 addData(SymTab);
1343
1344 return std::move(Obj);
1345}
1346
1347
1348
1349void IHexELFBuilder::addDataSections() {
1351 uint64_t SegmentAddr = 0, BaseAddr = 0;
1353
1354 for (const IHexRecord &R : Records) {
1356 switch (R.Type) {
1358
1359 if (R.HexData.empty())
1360 continue;
1361 RecAddr = R.Addr + SegmentAddr + BaseAddr;
1363
1364
1365
1366
1368 ".sec" + std::to_string(SecNo), RecAddr,
1370 SecNo++;
1371 }
1372 Section->appendHexData(R.HexData);
1373 break;
1375 break;
1377
1378 SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
1379 break;
1382 Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
1384 break;
1386
1387 BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
1388 break;
1389 default:
1391 }
1392 }
1393}
1394
1401 return std::move(Err);
1402 addDataSections();
1403
1404 return std::move(Obj);
1405}
1406
1407template
1409 std::optional ExtractPartition)
1410 : ElfFile(ElfObj.getELFFile()), Obj(Obj),
1411 ExtractPartition(ExtractPartition) {
1412 Obj.IsMips64EL = ElfFile.isMips64EL();
1413}
1414
1416 for (Segment &Parent : Obj.segments()) {
1417
1418
1420
1421
1426 }
1427 }
1428 }
1429}
1430
1432 if (!ExtractPartition)
1434
1435 for (const SectionBase &Sec : Obj.sections()) {
1437 EhdrOffset = Sec.Offset;
1439 }
1440 }
1442 "could not find partition named '" +
1443 *ExtractPartition + "'");
1444}
1445
1446template
1449
1452 if (!Headers)
1454
1456 if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
1459 "program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +
1461 " goes past the end of the file");
1462
1464 (size_t)Phdr.p_filesz};
1466 Seg.Type = Phdr.p_type;
1467 Seg.Flags = Phdr.p_flags;
1469 Seg.Offset = Phdr.p_offset + EhdrOffset;
1470 Seg.VAddr = Phdr.p_vaddr;
1471 Seg.PAddr = Phdr.p_paddr;
1472 Seg.FileSize = Phdr.p_filesz;
1473 Seg.MemSize = Phdr.p_memsz;
1474 Seg.Align = Phdr.p_align;
1481 }
1482 }
1483
1484 auto &ElfHdr = Obj.ElfHdrSegment;
1486 ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
1487
1488 const typename ELFT::Ehdr &Ehdr = HeadersFile.getHeader();
1489 auto &PrHdr = Obj.ProgramHdrSegment;
1491 PrHdr.Flags = 0;
1492
1493
1494
1495
1496 PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
1497 PrHdr.PAddr = 0;
1498 PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
1499
1500 PrHdr.Align = sizeof(Elf_Addr);
1501 PrHdr.Index = Index++;
1502
1503
1504
1505 for (Segment &Child : Obj.segments())
1506 setParentSegment(Child);
1507 setParentSegment(ElfHdr);
1508 setParentSegment(PrHdr);
1509
1511}
1512
1513template
1517 "invalid alignment " + Twine(GroupSec->Align) +
1518 " of group section '" + GroupSec->Name + "'");
1521 auto SymTab = SecTable.template getSectionOfType(
1522 GroupSec->Link,
1523 "link field value '" + Twine(GroupSec->Link) + "' in section '" +
1524 GroupSec->Name + "' is invalid",
1525 "link field value '" + Twine(GroupSec->Link) + "' in section '" +
1526 GroupSec->Name + "' is not a symbol table");
1527 if (!SymTab)
1528 return SymTab.takeError();
1529
1531 if ()
1533 "info field value '" + Twine(GroupSec->Info) +
1534 "' in section '" + GroupSec->Name +
1535 "' is not a valid symbol index");
1538 }
1542 "the content of the section " + GroupSec->Name +
1543 " is malformed");
1548 GroupSec->setFlagWord(endian::read32ELFT::Endianness(Word++));
1550 uint32_t Index = support::endian::read32ELFT::Endianness(Word);
1552 Index, "group member index " + Twine(Index) + " in section '" +
1553 GroupSec->Name + "' is invalid");
1554 if (!Sec)
1556
1558 }
1559
1561}
1562
1563template
1567 return Shdr.takeError();
1568
1570 if (!StrTabData)
1572
1574
1576 ElfFile.symbols(*Shdr);
1577 if (!Symbols)
1578 return Symbols.takeError();
1579
1582
1585 return Name.takeError();
1586
1590 "symbol '" + *Name +
1591 "' has index SHN_XINDEX but no "
1592 "SHT_SYMTAB_SHNDX section exists");
1593 if (ShndxData.data() == nullptr) {
1596 if (!ShndxSec)
1598
1600 ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);
1602 return Data.takeError();
1603
1604 ShndxData = *Data;
1605 if (ShndxData.size() != Symbols->size())
1608 "symbol section index table does not have the same number of "
1609 "entries as the symbol table");
1610 }
1611 Elf_Word Index = ShndxData[&Sym - Symbols->begin()];
1613 Index,
1614 "symbol '" + *Name + "' has invalid section index " + Twine(Index));
1615 if (!Sec)
1617
1618 DefSection = *Sec;
1623 "symbol '" + *Name +
1624 "' has unsupported value greater than or equal "
1625 "to SHN_LORESERVE: " +
1627 }
1630 Sym.st_shndx, "symbol '" + *Name +
1631 "' is defined has invalid section index " +
1633 if (!Sec)
1635
1636 DefSection = *Sec;
1637 }
1638
1640 Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
1641 }
1642
1644}
1645
1646template
1648
1649template
1651 ToSet = Rela.r_addend;
1652}
1653
1654template
1656 for (const auto &Rel : RelRange) {
1658 ToAdd.Offset = Rel.r_offset;
1661
1666 "'" + Relocs->Name + "': relocation references symbol with index " +
1667 Twine(Sym) + ", but there is no symbol table");
1670 if (!SymByIndex)
1672
1674 }
1675
1677 }
1678
1680}
1681
1684 if (Index == SHN_UNDEF || Index > Sections.size())
1686 return Sections[Index - 1].get();
1687}
1688
1689template
1691 Twine IndexErrMsg,
1692 Twine TypeErrMsg) {
1694 if (!BaseSec)
1696
1697 if (T *Sec = dyn_cast(*BaseSec))
1698 return Sec;
1699
1701}
1702
1703template
1705 switch (Shdr.sh_type) {
1712 else
1713 return Data.takeError();
1714 }
1717
1718
1719
1723 else
1724 return Data.takeError();
1725 }
1729
1730
1733 else
1734 return Data.takeError();
1738 else
1739 return Data.takeError();
1743 else
1744 return Data.takeError();
1748 else
1749 return Data.takeError();
1751
1752 if (Obj.SymbolTable != nullptr)
1754 "found multiple SHT_SYMTAB sections");
1756 Obj.SymbolTable = &SymTab;
1757 return SymTab;
1758 }
1761 Obj.SectionIndexTable = &ShndxSection;
1762 return ShndxSection;
1763 }
1766 default: {
1769 return Data.takeError();
1770
1773 return Name.takeError();
1774
1779 *Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));
1780 }
1781 }
1782}
1783
1787 ElfFile.sections();
1788 if (!Sections)
1790
1792 if (Index == 0) {
1794 continue;
1795 }
1797 if (!Sec)
1799
1801 if (!SecName)
1803 Sec->Name = SecName->str();
1804 Sec->Type = Sec->OriginalType = Shdr.sh_type;
1805 Sec->Flags = Sec->OriginalFlags = Shdr.sh_flags;
1806 Sec->Addr = Shdr.sh_addr;
1807 Sec->Offset = Shdr.sh_offset;
1808 Sec->OriginalOffset = Shdr.sh_offset;
1809 Sec->Size = Shdr.sh_size;
1810 Sec->Link = Shdr.sh_link;
1811 Sec->Info = Shdr.sh_info;
1812 Sec->Align = Shdr.sh_addralign;
1813 Sec->EntrySize = Shdr.sh_entsize;
1814 Sec->Index = Index++;
1815 Sec->OriginalIndex = Sec->Index;
1817 ElfFile.base() + Shdr.sh_offset,
1819 }
1820
1822}
1823
1825 uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
1828 if (!Sec)
1830
1831 ShstrIndex = (*Sec)->sh_link;
1832 }
1833
1835 Obj.HadShdrs = false;
1836 else {
1838 Obj.sections().template getSectionOfType(
1839 ShstrIndex,
1840 "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
1841 " is invalid",
1842 "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
1843 " does not reference a string table");
1844 if (!Sec)
1846
1847 Obj.SectionNames = *Sec;
1848 }
1849
1850
1851
1852
1853 if (Obj.SectionIndexTable)
1854 if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
1855 return Err;
1856
1857
1858
1859
1860 if (Obj.SymbolTable) {
1861 if (Error Err = Obj.SymbolTable->initialize(Obj.sections()))
1862 return Err;
1863 if (Error Err = initSymbolTable(Obj.SymbolTable))
1864 return Err;
1865 } else if (EnsureSymtab) {
1866 if (Error Err = Obj.addNewSymbolTable())
1867 return Err;
1868 }
1869
1870
1871
1872
1873 for (SectionBase &Sec : Obj.sections()) {
1874 if (&Sec == Obj.SymbolTable)
1875 continue;
1876 if (Error Err = Sec.initialize(Obj.sections()))
1877 return Err;
1878 if (auto RelSec = dyn_cast(&Sec)) {
1880 ElfFile.sections();
1881 if (!Sections)
1883
1885 Sections->begin() + RelSec->Index;
1886 if (RelSec->Type == SHT_CREL) {
1887 auto RelsOrRelas = ElfFile.crels(*Shdr);
1888 if (!RelsOrRelas)
1889 return RelsOrRelas.takeError();
1891 return Err;
1893 return Err;
1894 } else if (RelSec->Type == SHT_REL) {
1896 ElfFile.rels(*Shdr);
1897 if (!Rels)
1899
1901 return Err;
1902 } else {
1904 ElfFile.relas(*Shdr);
1905 if (!Relas)
1907
1909 return Err;
1910 }
1911 } else if (auto GroupSec = dyn_cast(&Sec)) {
1912 if (Error Err = initGroupSection(GroupSec))
1913 return Err;
1914 }
1915 }
1916
1918}
1919
1921 if (Error E = readSectionHeaders())
1922 return E;
1923 if (Error E = findEhdrOffset())
1924 return E;
1925
1926
1927
1928
1930 {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
1931 if (!HeadersFile)
1933
1936 Obj.OSABI = Ehdr.e_ident[EI_OSABI];
1938 Obj.Type = Ehdr.e_type;
1939 Obj.Machine = Ehdr.e_machine;
1940 Obj.Version = Ehdr.e_version;
1941 Obj.Entry = Ehdr.e_entry;
1942 Obj.Flags = Ehdr.e_flags;
1943
1944 if (Error E = readSections(EnsureSymtab))
1945 return E;
1946 return readProgramHeaders(*HeadersFile);
1947}
1948
1950
1952
1956}
1957
1960 std::vector Records;
1961 bool HasSections = false;
1962
1964 Records.reserve(Lines.size());
1965 for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
1966 StringRef Line = Lines[LineNo - 1].trim();
1967 if (Line.empty())
1968 continue;
1969
1971 if (!R)
1972 return parseError(LineNo, R.takeError());
1974 break;
1976 Records.push_back(*R);
1977 }
1978 if (!HasSections)
1979 return parseError(-1U, "no sections");
1980
1981 return std::move(Records);
1982}
1983
1987 if (!Records)
1988 return Records.takeError();
1989
1991}
1992
1994 auto Obj = std::make_unique();
1997 if (Error Err = Builder.build(EnsureSymtab))
1998 return std::move(Err);
1999 return std::move(Obj);
2002 if (Error Err = Builder.build(EnsureSymtab))
2003 return std::move(Err);
2004 return std::move(Obj);
2007 if (Error Err = Builder.build(EnsureSymtab))
2008 return std::move(Err);
2009 return std::move(Obj);
2012 if (Error Err = Builder.build(EnsureSymtab))
2013 return std::move(Err);
2014 return std::move(Obj);
2015 }
2017}
2018
2020 Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart());
2021 std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
2022 Ehdr.e_ident[EI_MAG0] = 0x7f;
2023 Ehdr.e_ident[EI_MAG1] = 'E';
2024 Ehdr.e_ident[EI_MAG2] = 'L';
2025 Ehdr.e_ident[EI_MAG3] = 'F';
2030 Ehdr.e_ident[EI_OSABI] = Obj.OSABI;
2032
2033 Ehdr.e_type = Obj.Type;
2034 Ehdr.e_machine = Obj.Machine;
2035 Ehdr.e_version = Obj.Version;
2036 Ehdr.e_entry = Obj.Entry;
2037
2038
2039 Ehdr.e_phnum = llvm::size(Obj.segments());
2040 Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
2041 Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
2042 Ehdr.e_flags = Obj.Flags;
2043 Ehdr.e_ehsize = sizeof(Elf_Ehdr);
2044 if (WriteSectionHeaders && Obj.sections().size() != 0) {
2045 Ehdr.e_shentsize = sizeof(Elf_Shdr);
2046 Ehdr.e_shoff = Obj.SHOff;
2047
2048
2049
2050
2051
2052
2053 auto Shnum = Obj.sections().size() + 1;
2055 Ehdr.e_shnum = 0;
2056 else
2057 Ehdr.e_shnum = Shnum;
2058
2059
2060
2061
2062
2063
2066 else
2067 Ehdr.e_shstrndx = Obj.SectionNames->Index;
2068 } else {
2069 Ehdr.e_shentsize = 0;
2070 Ehdr.e_shoff = 0;
2071 Ehdr.e_shnum = 0;
2072 Ehdr.e_shstrndx = 0;
2073 }
2074}
2075
2077 for (auto &Seg : Obj.segments())
2078 writePhdr(Seg);
2079}
2080
2082
2083
2084 Elf_Shdr &Shdr =
2085 *reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff);
2086 Shdr.sh_name = 0;
2088 Shdr.sh_flags = 0;
2089 Shdr.sh_addr = 0;
2090 Shdr.sh_offset = 0;
2091
2092 uint64_t Shnum = Obj.sections().size() + 1;
2094 Shdr.sh_size = Shnum;
2095 else
2096 Shdr.sh_size = 0;
2097
2098 if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
2099 Shdr.sh_link = Obj.SectionNames->Index;
2100 else
2101 Shdr.sh_link = 0;
2102 Shdr.sh_info = 0;
2103 Shdr.sh_addralign = 0;
2104 Shdr.sh_entsize = 0;
2105
2107 writeShdr(Sec);
2108}
2109
2112
2113
2114
2115 if (Sec.ParentSegment == nullptr)
2116 if (Error Err = Sec.accept(*SecWriter))
2117 return Err;
2118
2120}
2121
2123 for (Segment &Seg : Obj.segments()) {
2127 }
2128
2129 for (const auto &it : Obj.getUpdatedSections()) {
2132
2134 assert(Parent && "This section should've been part of a segment.");
2136 Sec->OriginalOffset - Parent->OriginalOffset + Parent->Offset;
2138 }
2139
2140
2141 for (auto &Sec : Obj.removedSections()) {
2142 Segment *Parent = Sec.ParentSegment;
2143 if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
2144 continue;
2147 std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size);
2148 }
2149}
2150
2151template
2153 bool OnlyKeepDebug)
2154 : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
2155 OnlyKeepDebug(OnlyKeepDebug) {}
2156
2159 [&](const SecPtr &Sec) { return Sec->Name == Name; });
2160 if (It == Sections.end())
2162 Name.str().c_str());
2163
2164 auto *OldSec = It->get();
2165 if (!OldSec->hasContents())
2168 "section '%s' cannot be updated because it does not have contents",
2169 Name.str().c_str());
2170
2171 if (Data.size() > OldSec->Size && OldSec->ParentSegment)
2173 "cannot fit data of size %zu into section '%s' "
2174 "with size %" PRIu64 " that is part of a segment",
2175 Data.size(), Name.str().c_str(), OldSec->Size);
2176
2177 if (!OldSec->ParentSegment) {
2178 *It = std::make_unique(*OldSec, Data);
2179 } else {
2180
2181 OldSec->Size = Data.size();
2182 UpdatedSections[OldSec] = Data;
2183 }
2184
2186}
2187
2189 bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
2190
2191 auto Iter = std::stable_partition(
2192 std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
2194 return false;
2195
2196
2197 if (isa(Sec))
2198 return true;
2199 if (auto RelSec = dyn_cast(Sec.get())) {
2200 if (auto ToRelSec = RelSec->getSection())
2201 return !ToRemove(*ToRelSec);
2202 }
2203
2205 auto GroupSec = cast(Sec.get());
2206 return !llvm::all_of(GroupSec->members(), ToRemove);
2207 }
2208 return true;
2209 });
2216
2217
2218
2219 std::unordered_set<const SectionBase *> RemoveSections;
2220 RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
2221 for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
2222 for (auto &Segment : Segments)
2224 RemoveSec->onRemove();
2225 RemoveSections.insert(RemoveSec.get());
2226 }
2227
2228
2229
2230
2231
2232
2233 for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
2234 if (Error E = KeepSec->removeSectionReferences(
2235 AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
2236 return RemoveSections.find(Sec) != RemoveSections.end();
2237 }))
2238 return E;
2239 }
2240
2241
2242
2243 std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
2244
2245 Sections.erase(Iter, std::end(Sections));
2247}
2248
2251 auto SectionIndexLess = [](const SecPtr &Lhs, const SecPtr &Rhs) {
2252 return Lhs->Index < Rhs->Index;
2253 };
2255 "Sections are expected to be sorted by Index");
2256
2257
2258 for (auto &I : FromTo)
2259 I.second->Index = I.first->Index;
2260
2261
2262 for (auto &Sec : Sections)
2263 Sec->replaceSectionReferences(FromTo);
2264
2266 false,
2267 [=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }))
2268 return E;
2269 llvm::sort(Sections, SectionIndexLess);
2271}
2272
2275 for (const SecPtr &Sec : Sections)
2277 return E;
2279}
2280
2283
2284
2289
2290
2291
2293 break;
2294 }
2295 }
2296 if (!StrTab)
2297 StrTab = &addSection();
2298
2300 SymTab.Name = ".symtab";
2303 return Err;
2304 SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
2305
2307
2309}
2310
2311
2314}
2315
2316
2317
2318
2322
2323
2324
2325
2326
2327 for (Segment *Seg : Segments) {
2328
2329
2330
2331
2336 } else {
2339 }
2341 }
2343}
2344
2345
2346
2347
2348
2349
2350
2351template
2353
2354
2355
2356
2357
2358
2359
2360
2361 std::vector<SectionBase *> OutOfSegmentSections;
2363 for (auto &Sec : Sections) {
2364 Sec.Index = Index++;
2365 if (Sec.ParentSegment != nullptr) {
2367 Sec.Offset =
2369 } else
2370 OutOfSegmentSections.push_back(&Sec);
2371 }
2372
2376 });
2377 for (auto *Sec : OutOfSegmentSections) {
2379 Sec->Offset = Offset;
2381 Offset += Sec->Size;
2382 }
2384}
2385
2386
2387
2389
2390
2391 std::vector<SectionBase *> Sections;
2394 for (auto &Sec : Obj.sections()) {
2395 Sec.Index = Index++;
2396 Sections.push_back(&Sec);
2397 }
2401 });
2402
2403 for (auto *Sec : Sections) {
2404 auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type == PT_LOAD
2405 ? Sec->ParentSegment->firstSection()
2406 : nullptr;
2407
2408
2409
2410 if (FirstSec && FirstSec == Sec)
2411 Off = alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);
2412
2413
2414
2415
2417 Sec->Offset = Off;
2418 continue;
2419 }
2420
2421 if (!FirstSec) {
2422
2423
2424 Off = Sec->Align ? alignTo(Off, Sec->Align) : Off;
2425 } else if (FirstSec != Sec) {
2426
2427
2428 Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
2429 }
2430 Sec->Offset = Off;
2431 Off += Sec->Size;
2432 }
2433 return Off;
2434}
2435
2436
2437
2441 for (Segment *Seg : Segments) {
2443 continue;
2444
2445
2446
2447
2448
2449
2450
2453 FirstSec ? FirstSec->Offset
2460 }
2461
2462
2463
2467 FileSize = std::max(FileSize, HdrEnd - Offset);
2468 }
2469
2472 MaxOffset = std::max(MaxOffset, Offset + FileSize);
2473 }
2474 return MaxOffset;
2475}
2476
2478 Segment &ElfHdr = Obj.ElfHdrSegment;
2480 ElfHdr.Flags = 0;
2481 ElfHdr.VAddr = 0;
2482 ElfHdr.PAddr = 0;
2484 ElfHdr.Align = 0;
2485}
2486
2488
2489
2490
2491 std::vector<Segment *> OrderedSegments;
2493 OrderedSegments.push_back(&Segment);
2494 OrderedSegments.push_back(&Obj.ElfHdrSegment);
2495 OrderedSegments.push_back(&Obj.ProgramHdrSegment);
2497
2499 if (OnlyKeepDebug) {
2500
2501
2502
2504 sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);
2508 } else {
2509
2510
2511
2514 }
2515
2516
2517 if (WriteSectionHeaders)
2520}
2521
2523
2524
2525 if (!WriteSectionHeaders)
2526 return Obj.SHOff;
2527 size_t ShdrCount = Obj.sections().size() + 1;
2528 return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
2529}
2530
2532
2533
2534 writeSegmentData();
2535 writeEhdr();
2536 writePhdrs();
2537 if (Error E = writeSectionData())
2538 return E;
2539 if (WriteSectionHeaders)
2540 writeShdrs();
2541
2542
2543
2544 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
2546}
2547
2549
2550
2551
2552
2556
2557
2558
2560 ? nullptr
2563 return &Sec == Obj.SymbolTable || &Sec == StrTab;
2564 });
2565}
2566
2568
2569
2570
2571 if (Obj.SectionNames == nullptr && WriteSectionHeaders)
2573 "cannot write section header table because "
2574 "section header string table was removed");
2575
2577 return E;
2578
2579
2580
2581 if (Obj.SymbolTable && !Obj.SymbolTable->indicesChanged())
2583 Sec.restoreSymTabLink(*Obj.SymbolTable);
2584
2585
2586
2587
2588 bool NeedsLargeIndexes = false;
2591
2592
2593 NeedsLargeIndexes =
2596
2597
2598 }
2599
2600 if (NeedsLargeIndexes) {
2601
2602
2603 if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
2604
2605
2607 Obj.SymbolTable->setShndxTable(&Shndx);
2608 Shndx.setSymTab(Obj.SymbolTable);
2609 }
2610 } else {
2611
2612
2613 if (Obj.SectionIndexTable != nullptr) {
2614
2615 if (Error E = Obj.removeSections(false ,
2617 return &Sec == Obj.SectionIndexTable;
2618 }))
2619 return E;
2620 }
2621 }
2622
2623
2624
2625 if (Obj.SectionNames != nullptr)
2626 for (const SectionBase &Sec : Obj.sections())
2627 Obj.SectionNames->addString(Sec.Name);
2628
2629 initEhdrSegment();
2630
2631
2632
2633
2635 auto SecSizer = std::make_unique<ELFSectionSizer>();
2636 for (SectionBase &Sec : Obj.sections()) {
2637 Sec.Index = Index++;
2638 if (Error Err = Sec.accept(*SecSizer))
2639 return Err;
2640 }
2641
2642
2643
2644
2645 if (Obj.SymbolTable != nullptr)
2646 Obj.SymbolTable->prepareForLayout();
2647
2648
2649
2651 if (auto StrTab = dyn_cast(&Sec))
2652 StrTab->prepareForLayout();
2653
2654 assignOffsets();
2655
2656
2657
2658 if (Obj.SymbolTable != nullptr)
2659 Obj.SymbolTable->fillShndxTable();
2660
2661
2662
2664 for (SectionBase &Sec : Obj.sections()) {
2665 Sec.HeaderOffset = Offset;
2666 Offset += sizeof(Elf_Shdr);
2667 if (WriteSectionHeaders)
2668 Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
2669 Sec.finalize();
2670 }
2671
2672 size_t TotalSize = totalSize();
2674 if (!Buf)
2676 "failed to allocate memory buffer of " +
2678
2679 SecWriter = std::make_unique<ELFSectionWriter>(*Buf);
2681}
2682
2686 if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
2687 SectionsToWrite.push_back(&Sec);
2688 }
2689
2690 if (SectionsToWrite.empty())
2692
2695 return LHS->Offset < RHS->Offset;
2696 });
2697
2698 assert(SectionsToWrite.front()->Offset == 0);
2699
2700 for (size_t i = 0; i != SectionsToWrite.size(); ++i) {
2701 const SectionBase &Sec = *SectionsToWrite[i];
2703 return Err;
2704 if (GapFill == 0)
2705 continue;
2706 uint64_t PadOffset = (i < SectionsToWrite.size() - 1)
2707 ? SectionsToWrite[i + 1]->Offset
2708 : Buf->getBufferSize();
2709 assert(PadOffset <= Buf->getBufferSize());
2711 std::fill(Buf->getBufferStart() + Sec.Offset + Sec.Size,
2712 Buf->getBufferStart() + PadOffset, GapFill);
2713 }
2714
2715
2716
2717 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
2719}
2720
2722
2723
2724
2725
2728 if (Sec.ParentSegment != nullptr)
2729 Sec.Addr =
2730 Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
2731 if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
2732 MinAddr = std::min(MinAddr, Sec.Addr);
2733 }
2734
2735
2736
2737
2738
2739 TotalSize = PadTo > MinAddr ? PadTo - MinAddr : 0;
2741 if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
2742 Sec.Offset = Sec.Addr - MinAddr;
2743 TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
2744 }
2745
2747 if ()
2749 "failed to allocate memory buffer of " +
2751 SecWriter = std::make_unique(*Buf);
2753}
2754
2760 "section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
2763}
2764
2766
2769 "entry point address 0x%llx overflows 32 bits",
2771
2775 return E;
2777 }
2778 }
2779
2782 });
2783
2784 std::unique_ptr EmptyBuffer =
2786 if (!EmptyBuffer)
2788 "failed to allocate memory buffer of 0 bytes");
2789
2791 if (!ExpTotalSize)
2792 return ExpTotalSize.takeError();
2794
2796 if ()
2798 "failed to allocate memory buffer of 0x" +
2801}
2802
2803uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
2806
2808 return 0;
2809
2810 if (Obj.Entry <= 0xFFFFFU) {
2811 Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
2815 } else {
2819 }
2820 memcpy(Buf, HexData.data(), HexData.size());
2821 return HexData.size();
2822}
2823
2824uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
2826 memcpy(Buf, HexData.data(), HexData.size());
2827 return HexData.size();
2828}
2829
2834 if (Error Err = Sec->accept(LengthCalc))
2835 return std::move(Err);
2836
2837
2838
2839 return LengthCalc.getBufferOffset() +
2842}
2843
2846
2849 return Err;
2850
2852
2853 Offset += writeEntryPointRecord(
2854 reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
2855
2856 Offset += writeEndOfFileRecord(
2857 reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
2859
2860
2861
2862 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
2864}
2865
2867
2869 "Expected section size to have been finalized");
2870
2871
2873}
2874
2878}
2879
2883}
2884
2888}
2889
2893}
2894
2896
2897
2903 Off += Record.getSize();
2904 }
2906}
2907
2910 const uint32_t ChunkSize = 16;
2914 while (.empty()) {
2915 uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
2918 Data = Data.drop_front(DataSize);
2920 }
2921}
2922
2925 "Section size does not match the section's string table builder size");
2926 std::vector<uint8_t> Data(Sec.Size);
2927 Sec.StrTabBuilder.write(Data.data());
2930}
2931
2934 auto *Iter = Line.begin();
2935 *Iter++ = 'S';
2936 *Iter++ = '0' + Type;
2937
2939
2941
2944
2946 *Iter++ = '\r';
2947 *Iter++ = '\n';
2948 assert(Iter == Line.end());
2949 return Line;
2950}
2951
2954 Sum += (Address >> 24) & 0xFF;
2955 Sum += (Address >> 16) & 0xFF;
2956 Sum += (Address >> 8) & 0xFF;
2959 Sum += Byte;
2960 return 0xFF - (Sum & 0xFF);
2961}
2962
2964
2966}
2967
2969 switch (Type) {
2971 return 6;
2973 return 8;
2975 return 8;
2977 return 6;
2978 default:
2979 return 4;
2980 }
2981}
2982
2985 uint8_t ChecksumSize = 1;
2986 return getAddressSize() / 2 + DataSize + ChecksumSize;
2987}
2988
2990 if (isUInt<16>(Address))
2992 if (isUInt<24>(Address))
2995}
2996
2998
2999
3000
3003 reinterpret_cast<const uint8_t *>(HeaderContents.data()),
3004 HeaderContents.size());
3006}
3007
3008size_t SRECWriter::writeHeader(uint8_t *Buf) {
3011 return Record.size();
3012}
3013
3016 "Invalid record type for terminator");
3020 return Data.size();
3021}
3022
3027 if (Error Err = Sec->accept(SizeCalc))
3028 return std::move(Err);
3029
3030 SizeCalc.writeRecords(Obj.Entry);
3031
3033 uint8_t TerminatorType = 10 - SizeCalc.getType();
3035 return Header.getSize() + SizeCalc.getBufferOffset() + Terminator.getSize();
3036}
3037
3040 writeHeader(reinterpret_cast<uint8_t *>(Buf->getBufferStart()));
3044 return E;
3045 }
3048
3049
3051 Offset += writeTerminator(
3052 reinterpret_cast<uint8_t *>(Buf->getBufferStart() + Offset),
3053 TerminatorType);
3055 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
3057}
3058
3059namespace llvm {
3060namespace objcopy {
3061namespace elf {
3062
3067
3072
3073}
3074}
3075}
ReachingDefAnalysis InstSet & ToRemove
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
COFF::MachineTypes Machine
Analysis containing CSE Info
static bool segmentOverlapsSegment(const Segment &Child, const Segment &Parent)
static void setAddend(Elf_Rel_Impl< ELFT, false > &, uint64_t)
static Error checkChars(StringRef Line)
static void orderSegments(std::vector< Segment * > &Segments)
static uint64_t layoutSegments(std::vector< Segment * > &Segments, uint64_t Offset)
static bool compareSegmentsByOffset(const Segment *A, const Segment *B)
static uint64_t layoutSections(Range Sections, uint64_t Offset)
static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off)
static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine)
static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector< Segment * > &Segments, uint64_t HdrEnd)
static void getAddend(uint64_t &, const Elf_Rel_Impl< ELFT, false > &)
static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL)
static bool addressOverflows32bit(uint64_t Addr)
static T checkedGetHex(StringRef S)
static uint64_t sectionPhysicalAddr(const SectionBase *Sec)
static Iterator toHexStr(T X, Iterator It, size_t Len)
static Error checkRecord(const IHexRecord &R)
static Error initRelocations(RelocationSection *Relocs, T RelRange)
static Error removeUnneededSections(Object &Obj)
static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
size_t getBufferSize() const
StringRef getBuffer() const
const char * getBufferStart() const
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
size_t getOffset(CachedHashStringRef S) const
Get the offest of a string in the string table.
void write(raw_ostream &OS) const
size_t add(CachedHashStringRef S)
Add a string to the builder.
void finalize()
Analyze the strings and build the final table.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(const uint64_t &Val)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class is an extension of MemoryBuffer, which allows copy-on-write access to the underlying conte...
static std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
An efficient, type-erasing, non-owning reference to a callable.
Error checkSection(const SectionBase &S) const
Error finalize() override
std::vector< const SectionBase * > Sections
virtual Expected< size_t > getTotalSize(WritableMemoryBuffer &EmptyBuffer) const =0
StringTableSection * addStrTab()
SymbolTableSection * addSymTab(StringTableSection *StrTab)
std::unique_ptr< Object > Obj
Expected< std::unique_ptr< Object > > build()
Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const override
Error visit(const SymbolTableSection &Sec) override
Error finalize() override
Error accept(SectionVisitor &Visitor) const override
CompressedSection(const SectionBase &Sec, DebugCompressionType CompressionType, bool Is64Bits)
Error accept(SectionVisitor &Visitor) const override
Error accept(SectionVisitor &) const override
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
ELFBuilder(const ELFObjectFile< ELFT > &ElfObj, Object &Obj, std::optional< StringRef > ExtractPartition)
Error build(bool EnsureSymtab)
Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const override
Error visit(Section &Sec) override
Error visit(const SymbolTableSection &Sec) override
Error finalize() override
ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug)
Error accept(SectionVisitor &Visitor) const override
GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC)
void setSymTab(const SymbolTableSection *SymTabSec)
void setSymbol(Symbol *S)
void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &FromTo) override
Error accept(SectionVisitor &) const override
void markSymbols() override
ArrayRef< uint8_t > Contents
void addMember(SectionBase *Sec)
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
void setFlagWord(ELF::Elf32_Word W)
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove) override
Expected< std::unique_ptr< Object > > build()
Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const override
void writeSection(const SectionBase *Sec, ArrayRef< uint8_t > Data)
Error visit(const Section &Sec) final
virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef< uint8_t > Data)
void writeData(uint8_t Type, uint16_t Addr, ArrayRef< uint8_t > Data) override
Error visit(const StringTableSection &Sec) override
virtual Error visit(Section &Sec)=0
SectionTableRef sections() const
StringTableSection * SectionNames
bool isRelocatable() const
iterator_range< filter_iterator< pointee_iterator< std::vector< SecPtr >::const_iterator >, decltype(§ionIsAlloc)> > allocSections() const
Error updateSection(StringRef Name, ArrayRef< uint8_t > Data)
SectionIndexSection * SectionIndexTable
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove)
Error removeSections(bool AllowBrokenLinks, std::function< bool(const SectionBase &)> ToRemove)
SymbolTableSection * SymbolTable
Error addNewSymbolTable()
Error replaceSections(const DenseMap< SectionBase *, SectionBase * > &FromTo)
void appendHexData(StringRef HexData)
Error accept(SectionVisitor &Sec) const override
Error initialize(SectionTableRef SecTable) override
SymbolTableSection * Symbols
SectionBase * SecToApplyRel
StringRef getNamePrefix() const
void markSymbols() override
const Object & getObject() const
void addRelocation(const Relocation &Rel)
Error accept(SectionVisitor &Visitor) const override
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove) override
void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &FromTo) override
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
std::vector< SRecord > Records
virtual void writeRecord(SRecord &Record, uint64_t Off)=0
void writeSection(const SectionBase &S, ArrayRef< uint8_t > Data)
Error visit(const Section &S) override
void writeRecords(uint32_t Entry)
Error visit(const StringTableSection &Sec) override
void writeRecord(SRecord &Record, uint64_t Off) override
virtual void markSymbols()
ArrayRef< uint8_t > OriginalData
virtual Error initialize(SectionTableRef SecTable)
virtual Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove)
virtual void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &)
virtual Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove)
virtual Error accept(SectionVisitor &Visitor) const =0
void addIndex(uint32_t Index)
void setSymTab(SymbolTableSection *SymTab)
Error accept(SectionVisitor &Visitor) const override
void reserve(size_t NumSymbols)
Error initialize(SectionTableRef SecTable) override
Expected< T * > getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg)
Expected< SectionBase * > getSection(uint32_t Index, Twine ErrMsg)
virtual Error visit(const Section &Sec)=0
Error visit(const Section &Sec) override
WritableMemoryBuffer & Out
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
Error initialize(SectionTableRef SecTable) override
void restoreSymTabLink(SymbolTableSection &SymTab) override
Error accept(SectionVisitor &Visitor) const override
void addSection(const SectionBase *Sec)
void removeSection(const SectionBase *Sec)
const SectionBase * firstSection() const
ArrayRef< uint8_t > getContents() const
std::set< const SectionBase *, SectionCompare > Sections
void addString(StringRef Name)
uint32_t findIndex(StringRef Name) const
Error accept(SectionVisitor &Visitor) const override
const SectionBase * getStrTab() const
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
const SectionIndexSection * getShndxTable() const
std::vector< std::unique_ptr< Symbol > > Symbols
SectionIndexSection * SectionIndexTable
Error accept(SectionVisitor &Visitor) const override
void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, uint16_t Shndx, uint64_t SymbolSize)
void updateSymbols(function_ref< void(Symbol &)> Callable)
Expected< const Symbol * > getSymbolByIndex(uint32_t Index) const
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove) override
Error initialize(SectionTableRef SecTable) override
void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &FromTo) override
std::unique_ptr< Symbol > SymPtr
void setShndxTable(SectionIndexSection *ShndxTable)
StringTableSection * SymbolNames
std::unique_ptr< WritableMemoryBuffer > Buf
const Elf_Ehdr & getHeader() const
static Expected< ELFFile > create(StringRef Object)
Expected< Elf_Phdr_Range > program_headers() const
Iterate over program header table.
size_t getBufSize() const
const uint8_t * base() const
Represents a GOFF physical record.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an SmallVector or SmallString.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
void encodeCrel(raw_ostream &OS, RelocsTy Relocs, F ToCrel)
const char * getReasonIfUnsupported(Format F)
Error decompress(DebugCompressionType T, ArrayRef< uint8_t > Input, uint8_t *Output, size_t UncompressedSize)
Format formatFor(DebugCompressionType Type)
void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
support::ulittle32_t Word
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void stable_sort(R &&Range)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
@ operation_not_permitted
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
@ Mod
The access may modify the value stored in memory.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt copy(R &&Range, OutputIt Out)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
const char * toString(DWARFSectionKind Kind)
This struct is a compact representation of a valid (non-zero power of two) alignment.
static IHexLineData getLine(uint8_t Type, uint16_t Addr, ArrayRef< uint8_t > Data)
static uint8_t getChecksum(StringRef S)
static Expected< IHexRecord > parse(StringRef Line)
static size_t getLength(size_t DataSize)
static size_t getLineLength(size_t DataSize)
uint8_t getAddressSize() const
static SRecord getHeader(StringRef FileName)
uint8_t getChecksum() const
SRecLineData toString() const
static uint8_t getType(uint32_t Address)
uint16_t getShndx() const
SymbolShndxType ShndxType