llvm.org GIT mirror llvm / 6595d58
[llvm-objcopy] Implement IHEX writer Differential revision: https://reviews.llvm.org/D60270 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361949 91177308-0d34-0410-b5e6-96231b3b80d8 Eugene Leviant 4 months ago
10 changed file(s) with 717 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
11761176 class FileError final : public ErrorInfo {
11771177
11781178 friend Error createFileError(const Twine &, Error);
1179 friend Error createFileError(const Twine &, size_t, Error);
11791180
11801181 public:
11811182 void log(raw_ostream &OS) const override {
11821183 assert(Err && !FileName.empty() && "Trying to log after takeError().");
11831184 OS << "'" << FileName << "': ";
1185 if (Line.hasValue())
1186 OS << "line " << Line.getValue() << ": ";
11841187 Err->log(OS);
11851188 }
11861189
11921195 static char ID;
11931196
11941197 private:
1195 FileError(const Twine &F, std::unique_ptr E) {
1198 FileError(const Twine &F, Optional LineNum,
1199 std::unique_ptr E) {
11961200 assert(E && "Cannot create FileError from Error success value.");
11971201 assert(!F.isTriviallyEmpty() &&
11981202 "The file name provided to FileError must not be empty.");
11991203 FileName = F.str();
12001204 Err = std::move(E);
1201 }
1202
1203 static Error build(const Twine &F, Error E) {
1204 return Error(std::unique_ptr(new FileError(F, E.takePayload())));
1205 Line = std::move(LineNum);
1206 }
1207
1208 static Error build(const Twine &F, Optional Line, Error E) {
1209 return Error(
1210 std::unique_ptr(new FileError(F, Line, E.takePayload())));
12051211 }
12061212
12071213 std::string FileName;
1214 Optional Line;
12081215 std::unique_ptr Err;
12091216 };
12101217
12111218 /// Concatenate a source file path and/or name with an Error. The resulting
12121219 /// Error is unchecked.
12131220 inline Error createFileError(const Twine &F, Error E) {
1214 return FileError::build(F, std::move(E));
1221 return FileError::build(F, Optional(), std::move(E));
1222 }
1223
1224 /// Concatenate a source file path and/or name with line number and an Error.
1225 /// The resulting Error is unchecked.
1226 inline Error createFileError(const Twine &F, size_t Line, Error E) {
1227 return FileError::build(F, Optional(Line), std::move(E));
12151228 }
12161229
12171230 /// Concatenate a source file path and/or name with a std::error_code
12181231 /// to form an Error object.
12191232 inline Error createFileError(const Twine &F, std::error_code EC) {
12201233 return createFileError(F, errorCodeToError(EC));
1234 }
1235
1236 /// Concatenate a source file path and/or name with line number and
1237 /// std::error_code to form an Error object.
1238 inline Error createFileError(const Twine &F, size_t Line, std::error_code EC) {
1239 return createFileError(F, Line, errorCodeToError(EC));
12211240 }
12221241
12231242 Error createFileError(const Twine &F, ErrorSuccess) = delete;
0 !ELF
1 FileHeader:
2 Class: ELFCLASS64
3 Data: ELFDATA2LSB
4 Type: ET_EXEC
5 Machine: EM_X86_64
6 Sections:
7 - Name: .text
8 Type: SHT_PROGBITS
9 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
10 Address: 0x0
11 AddressAlign: 0x8
12 Content: "0001020304"
13 ProgramHeaders:
14 - Type: PT_NULL
15 Flags: [ PF_X, PF_R ]
16 VAddr: 0xF00000000
17 PAddr: 0x100000
18 Sections:
19 - Section: .text
0 !ELF
1 FileHeader:
2 Class: ELFCLASS64
3 Data: ELFDATA2LSB
4 Type: ET_EXEC
5 Machine: EM_X86_64
6 Sections:
7 - Name: .text
8 # This section contents exceeds default IHex line length of 16 bytes
9 # so we expect two lines created for it.
10 Type: SHT_PROGBITS
11 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
12 Address: 0x0
13 AddressAlign: 0x8
14 Content: "000102030405060708090A0B0C0D0E0F1011121314"
15 - Name: .data
16 # This section overlap 16-bit segment boundary, so we expect
17 # additional 'SegmentAddr' record of type '02'
18 Type: SHT_PROGBITS
19 Flags: [ SHF_ALLOC ]
20 Content: "3031323334353637383940"
21 Address: 0xFFF8
22 AddressAlign: 0x8
23 - Name: .data2
24 # Previous section '.data' should have forced creation of
25 # 'SegmentAddr'(02) record with segment address of 0x10000,
26 # so this section should have address of 0x100.
27 Type: SHT_PROGBITS
28 Flags: [ SHF_ALLOC ]
29 Content: "40414243"
30 Address: 0x10100
31 AddressAlign: 0x8
32 - Name: .data3
33 # The last section not only overlaps segment boundary, but
34 # also has linear address which doesn't fit 20 bits. The
35 # following records should be craeted:
36 # 'SegmentAddr'(02) record with address 0x0
37 # 'ExtendedAddr'(04) record with address 0x100000
38 # 'Data'(00) record with 8 bytes of section data
39 # 'SegmentAddr'(02) record with address 0x10000
40 # 'Data'(00) record with remaining 3 bytes of data.
41 Type: SHT_PROGBITS
42 Flags: [ SHF_ALLOC ]
43 Content: "5051525354555657585960"
44 Address: 0x10FFF8
45 AddressAlign: 0x8
46 - Name: .bss
47 # NOBITS sections are not written to IHex
48 Type: SHT_NOBITS
49 Flags: [ SHF_ALLOC ]
50 Address: 0x10100
51 Size: 0x1000
52 AddressAlign: 0x8
53 - Name: .dummy
54 # Non-allocatable sections are not written to IHex
55 Type: SHT_PROGBITS
56 Flags: [ ]
57 Address: 0x20FFF8
58 Size: 65536
59 AddressAlign: 0x8
0 !ELF
1 FileHeader:
2 Class: ELFCLASS64
3 Data: ELFDATA2LSB
4 Type: ET_EXEC
5 Machine: EM_X86_64
6 Sections:
7 - Name: .text
8 # Zero length sections are not exported to IHex
9 # 'SegmentAddr' and 'ExtendedAddr' records aren't
10 # created either.
11 Type: SHT_PROGBITS
12 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
13 Address: 0x7FFFFFFF
14 AddressAlign: 0x8
15 Size: 0
16 - Name: .text1
17 # Section address is sign-extended 32-bit address
18 # Data fits 32-bit range
19 Type: SHT_PROGBITS
20 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
21 Address: 0xFFFFFFFF80001000
22 AddressAlign: 0x8
23 Content: "0001020304"
24 - Name: .text2
25 # Part of section data is in 32-bit address range
26 # and part isn't.
27 Type: SHT_PROGBITS
28 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
29 Address: 0xFFFFFFF8
30 AddressAlign: 0x8
31 Content: "000102030405060708"
32 - Name: .text3
33 # Entire secion is outside of 32-bit range
34 Type: SHT_PROGBITS
35 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
36 Address: 0xFFFFFFFF0
37 AddressAlign: 0x8
38 Content: "0001020304"
0 # Here we use yaml from ihex-elf-sections.yaml, but add single load
1 # segment containing all exported sections. In such case we should
2 # use physical address of a section intead of virtual address. Physical
3 # addresses start from 0x100000, so we create two additional 'ExtenededAddr'
4 # (03) record in the beginning of IHex file with that physical address
5 !ELF
6 FileHeader:
7 Class: ELFCLASS64
8 Data: ELFDATA2LSB
9 Type: ET_EXEC
10 Machine: EM_X86_64
11 Entry: 0x100000
12 Sections:
13 - Name: .text
14 Type: SHT_PROGBITS
15 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
16 Address: 0x0
17 AddressAlign: 0x8
18 Content: "000102030405060708090A0B0C0D0E0F1011121314"
19 - Name: .data1
20 Type: SHT_PROGBITS
21 Flags: [ SHF_ALLOC ]
22 Content: "3031323334353637383940"
23 Address: 0xFFF8
24 AddressAlign: 0x8
25 - Name: .data2
26 Type: SHT_PROGBITS
27 Flags: [ SHF_ALLOC ]
28 Content: "40414243"
29 Address: 0x10100
30 AddressAlign: 0x8
31 - Name: .data3
32 Type: SHT_PROGBITS
33 Flags: [ SHF_ALLOC ]
34 Content: "5051525354555657585960"
35 Address: 0x10FFF8
36 AddressAlign: 0x8
37 - Name: .bss
38 Type: SHT_NOBITS
39 Flags: [ SHF_ALLOC ]
40 Address: 0x10100
41 Size: 0x1000
42 AddressAlign: 0x8
43 - Name: .dummy
44 Type: SHT_PROGBITS
45 Flags: [ ]
46 Address: 0x20FFF8
47 Size: 65536
48 AddressAlign: 0x8
49 ProgramHeaders:
50 - Type: PT_LOAD
51 Flags: [ PF_X, PF_R ]
52 VAddr: 0xF00000000
53 PAddr: 0x100000
54 Sections:
55 - Section: .text
56 - Section: .data1
57 - Section: .data2
58 - Section: .data3
59 - Section: .bss
0 # RUN: yaml2obj %p/Inputs/ihex-elf-sections.yaml -o %t
1 # RUN: llvm-objcopy -O ihex %t - | FileCheck %s
2
3 # Check ihex output, when we have segments in ELF file
4 # In such case only sections in PT_LOAD segments will
5 # be exported and their physical addresses will be used
6 # RUN: yaml2obj %p/Inputs/ihex-elf-segments.yaml -o %t-segs
7 # RUN: llvm-objcopy -O ihex %t-segs - | FileCheck %s --check-prefix=SEGMENTS
8
9 # Check that non-load segments are ignored:
10 # RUN: yaml2obj %p/Inputs/ihex-elf-pt-null.yaml -o %t2-segs
11 # RUN: llvm-objcopy -O ihex %t2-segs - | FileCheck %s --check-prefix=PT_NULL
12
13 # Check that sign-extended 32-bit section addresses are processed
14 # correctly
15 # RUN: yaml2obj %p/Inputs/ihex-elf-sections2.yaml -o %t-sec2
16 # RUN: llvm-objcopy -O ihex --only-section=.text1 %t-sec2 - | FileCheck %s --check-prefix=SIGN_EXTENDED
17
18 # Check that section address range overlapping 32 bit range
19 # triggers an error
20 # RUN: not llvm-objcopy -O ihex --only-section=.text2 %t-sec2 %t-sec2-2.hex 2>&1 | FileCheck %s --check-prefix=BAD-ADDR
21 # RUN: not llvm-objcopy -O ihex --only-section=.text3 %t-sec2 %t-sec2-3.hex 2>&1 | FileCheck %s --check-prefix=BAD-ADDR2
22
23 # Check that zero length section is not written
24 # RUN: llvm-objcopy -O ihex --only-section=.text %t-sec2 - | FileCheck %s --check-prefix=ZERO_SIZE_SEC
25
26 # Check 80x86 start address record. It is created for start
27 # addresses less than 0x100000
28 # RUN: llvm-objcopy -O ihex --set-start=0xFFFF %t - | FileCheck %s --check-prefix=START1
29
30 # Check i386 start address record (05). It is created for
31 # start addresses which doesn't fit 20 bits
32 # RUN: llvm-objcopy -O ihex --set-start=0x100000 %t - | FileCheck %s --check-prefix=START2
33
34 # We allow sign extended 32 bit start addresses as well.
35 # RUN: llvm-objcopy -O ihex --set-start=0xFFFFFFFF80001000 %t - | FileCheck %s --check-prefix=START3
36
37 # Start address which exceeds 32 bit range triggers an error
38 # RUN: not llvm-objcopy -O ihex --set-start=0xF00000000 %t %t6.hex 2>&1 | FileCheck %s --check-prefix=BAD-START
39
40 # CHECK: :10000000000102030405060708090A0B0C0D0E0F78
41 # CHECK-NEXT: :05001000101112131491
42 # CHECK-NEXT: :08FFF800303132333435363765
43 # CHECK-NEXT: :020000021000EC
44 # CHECK-NEXT: :030000003839404C
45 # CHECK-NEXT: :0401000040414243F5
46 # CHECK-NEXT: :020000020000FC
47 # CHECK-NEXT: :020000040010EA
48 # CHECK-NEXT: :08FFF800505152535455565765
49 # CHECK-NEXT: :020000040011E9
50 # CHECK-NEXT: :03000000585960EC
51 # CHECK-NEXT: :00000001FF
52
53 # SEGMENTS: :020000040010EA
54 # SEGMENTS-NEXT: :10000000000102030405060708090A0B0C0D0E0F78
55 # SEGMENTS-NEXT: :05001000101112131491
56 # SEGMENTS-NEXT: :0B001800303132333435363738394090
57 # SEGMENTS-NEXT: :0400280040414243CE
58 # SEGMENTS-NEXT: :0B003000505152535455565758596018
59 # SEGMENTS-NEXT: :0400000500100000E7
60 # SEGMENTS-NEXT: :00000001FF
61
62 # 'ExtendedAddr' (04) record shouldn't be created
63 # PT_NULL-NOT: :02000004
64
65 # SIGN_EXTENDED: :0200000480007A
66 # SIGN_EXTENDED-NEXT: :051000000001020304E1
67 # SIGN_EXTENDED-NEXT: :00000001FF
68
69 # BAD-ADDR: error: {{.*}}: Section '.text2' address range [0xfffffff8, 0x100000000] is not 32 bit
70 # BAD-ADDR2: error: {{.*}}: Section '.text3' address range [0xffffffff0, 0xffffffff4] is not 32 bit
71
72 # There shouldn't be 'ExtendedAddr' nor 'Data' records
73 # ZERO_SIZE_SEC-NOT: :02000004
74 # ZERO_SIZE_SEC-NOT: :00FFFF00
75 # ZERO_SIZE_SEC: :00000001FF
76
77 # START1: :040000030000FFFFFB
78 # START2: :0400000500100000E7
79 # START3: :040000058000100067
80 # BAD-START: error: {{.*}}: Entry point address 0xf00000000 overflows 32 bits
457457 return MI.takeError();
458458 Config.BinaryArch = *MI;
459459 }
460 if (!Config.OutputFormat.empty() && Config.OutputFormat != "binary") {
460 if (!Config.OutputFormat.empty() && Config.OutputFormat != "binary" &&
461 Config.OutputFormat != "ihex") {
461462 Expected MI = getOutputFormatMachineInfo(Config.OutputFormat);
462463 if (!MI)
463464 return MI.takeError();
129129 return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
130130 }
131131
132 static std::unique_ptr createWriter(const CopyConfig &Config,
133 Object &Obj, Buffer &Buf,
134 ElfType OutputElfType) {
135 if (Config.OutputFormat == "binary") {
136 return llvm::make_unique(Obj, Buf);
137 }
132 static std::unique_ptr createELFWriter(const CopyConfig &Config,
133 Object &Obj, Buffer &Buf,
134 ElfType OutputElfType) {
138135 // Depending on the initial ELFT and OutputFormat we need a different Writer.
139136 switch (OutputElfType) {
140137 case ELFT_ELF32LE:
151148 !Config.StripSections);
152149 }
153150 llvm_unreachable("Invalid output format");
151 }
152
153 static std::unique_ptr createWriter(const CopyConfig &Config,
154 Object &Obj, Buffer &Buf,
155 ElfType OutputElfType) {
156 using Functor = std::function()>;
157 return StringSwitch(Config.OutputFormat)
158 .Case("binary", [&] { return llvm::make_unique(Obj, Buf); })
159 .Case("ihex", [&] { return llvm::make_unique(Obj, Buf); })
160 .Default(
161 [&] { return createELFWriter(Config, Obj, Buf, OutputElfType); })();
154162 }
155163
156164 template
713721 return Error::success();
714722 }
715723
724 static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out,
725 ElfType OutputElfType) {
726 std::unique_ptr Writer =
727 createWriter(Config, Obj, Out, OutputElfType);
728 if (Error E = Writer->finalize())
729 return E;
730 return Writer->write();
731 }
732
716733 Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
717734 Buffer &Out) {
718735 BinaryReader Reader(Config.BinaryArch, &In);
720737
721738 // Prefer OutputArch (-O) if set, otherwise fallback to BinaryArch
722739 // (-B).
723 const ElfType OutputElfType = getOutputElfType(
724 Config.OutputArch ? Config.OutputArch.getValue() : Config.BinaryArch);
740 const ElfType OutputElfType =
741 getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch));
725742 if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType))
726743 return E;
727 std::unique_ptr Writer =
728 createWriter(Config, *Obj, Out, OutputElfType);
729 if (Error E = Writer->finalize())
730 return E;
731 return Writer->write();
744 return writeOutput(Config, *Obj, Out, OutputElfType);
732745 }
733746
734747 Error executeObjcopyOnBinary(const CopyConfig &Config,
763776 if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType))
764777 return createFileError(Config.InputFilename, std::move(E));
765778
766 std::unique_ptr Writer =
767 createWriter(Config, *Obj, Out, OutputElfType);
768 if (Error E = Writer->finalize())
779 if (Error E = writeOutput(Config, *Obj, Out, OutputElfType))
769780 return createFileError(Config.InputFilename, std::move(E));
770 if (Error E = Writer->write())
771 return E;
772781 if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput)
773782 if (Error E =
774783 linkToBuildIdDir(Config, Config.OutputFilename,
1616 #include "llvm/MC/MCTargetOptions.h"
1717 #include "llvm/Object/ELFObjectFile.h"
1818 #include "llvm/Support/Compression.h"
19 #include "llvm/Support/Errc.h"
19 #include "llvm/Support/Endian.h"
2020 #include "llvm/Support/ErrorHandling.h"
2121 #include "llvm/Support/FileOutputBuffer.h"
2222 #include "llvm/Support/Path.h"
146146 llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
147147 }
148148
149 static bool addressOverflows32bit(uint64_t Addr) {
150 // Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok
151 return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
152 }
153
154 template static T checkedGetHex(StringRef S) {
155 T Value;
156 bool Fail = S.getAsInteger(16, Value);
157 assert(!Fail);
158 (void)Fail;
159 return Value;
160 }
161
162 // Fills exactly Len bytes of buffer with hexadecimal characters
163 // representing value 'X'
164 template
165 static Iterator utohexstr(T X, Iterator It, size_t Len) {
166 // Fill range with '0'
167 std::fill(It, It + Len, '0');
168
169 for (long I = Len - 1; I >= 0; --I) {
170 unsigned char Mod = static_cast(X) & 15;
171 *(It + I) = hexdigit(Mod, false);
172 X >>= 4;
173 }
174 assert(X == 0);
175 return It + Len;
176 }
177
178 uint8_t IHexRecord::getChecksum(StringRef S) {
179 assert((S.size() & 1) == 0);
180 uint8_t Checksum = 0;
181 while (!S.empty()) {
182 Checksum += checkedGetHex(S.take_front(2));
183 S = S.drop_front(2);
184 }
185 return -Checksum;
186 }
187
188 IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,
189 ArrayRef Data) {
190 IHexLineData Line(getLineLength(Data.size()));
191 assert(Line.size());
192 auto Iter = Line.begin();
193 *Iter++ = ':';
194 Iter = utohexstr(Data.size(), Iter, 2);
195 Iter = utohexstr(Addr, Iter, 4);
196 Iter = utohexstr(Type, Iter, 2);
197 for (uint8_t X : Data)
198 Iter = utohexstr(X, Iter, 2);
199 StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
200 Iter = utohexstr(getChecksum(S), Iter, 2);
201 *Iter++ = '\r';
202 *Iter++ = '\n';
203 assert(Iter == Line.end());
204 return Line;
205 }
206
207 static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
208 Segment *Seg = Sec->ParentSegment;
209 if (Seg && Seg->Type != ELF::PT_LOAD)
210 Seg = nullptr;
211 return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset
212 : Sec->Addr;
213 }
214
215 void IHexSectionWriterBase::writeSection(const SectionBase *Sec,
216 ArrayRef Data) {
217 assert(Data.size() == Sec->Size);
218 const uint32_t ChunkSize = 16;
219 uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;
220 while (!Data.empty()) {
221 uint64_t DataSize = std::min(Data.size(), ChunkSize);
222 if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
223 if (Addr > 0xFFFFFU) {
224 // Write extended address record, zeroing segment address
225 // if needed.
226 if (SegmentAddr != 0)
227 SegmentAddr = writeSegmentAddr(0U);
228 BaseAddr = writeBaseAddr(Addr);
229 } else {
230 // We can still remain 16-bit
231 SegmentAddr = writeSegmentAddr(Addr);
232 }
233 }
234 uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
235 assert(SegOffset <= 0xFFFFU);
236 DataSize = std::min(DataSize, 0x10000U - SegOffset);
237 writeData(0, SegOffset, Data.take_front(DataSize));
238 Addr += DataSize;
239 Data = Data.drop_front(DataSize);
240 }
241 }
242
243 uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {
244 assert(Addr <= 0xFFFFFU);
245 uint8_t Data[] = {static_cast((Addr & 0xF0000U) >> 12), 0};
246 writeData(2, 0, Data);
247 return Addr & 0xF0000U;
248 }
249
250 uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {
251 assert(Addr <= 0xFFFFFFFFU);
252 uint64_t Base = Addr & 0xFFFF0000U;
253 uint8_t Data[] = {static_cast(Base >> 24),
254 static_cast((Base >> 16) & 0xFF)};
255 writeData(4, 0, Data);
256 return Base;
257 }
258
259 void IHexSectionWriterBase::writeData(uint8_t Type, uint16_t Addr,
260 ArrayRef Data) {
261 Offset += IHexRecord::getLineLength(Data.size());
262 }
263
264 void IHexSectionWriterBase::visit(const Section &Sec) {
265 writeSection(&Sec, Sec.Contents);
266 }
267
268 void IHexSectionWriterBase::visit(const OwnedDataSection &Sec) {
269 writeSection(&Sec, Sec.Data);
270 }
271
272 void IHexSectionWriterBase::visit(const StringTableSection &Sec) {
273 // Check that sizer has already done its work
274 assert(Sec.Size == Sec.StrTabBuilder.getSize());
275 // We are free to pass an invalid pointer to writeSection as long
276 // as we don't actually write any data. The real writer class has
277 // to override this method .
278 writeSection(&Sec, {nullptr, Sec.Size});
279 }
280
281 void IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) {
282 writeSection(&Sec, Sec.Contents);
283 }
284
285 void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,
286 ArrayRef Data) {
287 IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);
288 memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());
289 Offset += HexData.size();
290 }
291
292 void IHexSectionWriter::visit(const StringTableSection &Sec) {
293 assert(Sec.Size == Sec.StrTabBuilder.getSize());
294 std::vector Data(Sec.Size);
295 Sec.StrTabBuilder.write(Data.data());
296 writeSection(&Sec, Data);
297 }
298
149299 void Section::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); }
150300
151301 void Section::accept(MutableSectionVisitor &Visitor) { Visitor.visit(*this); }
214364
215365 void OwnedDataSection::accept(MutableSectionVisitor &Visitor) {
216366 Visitor.visit(*this);
367 }
368
369 void OwnedDataSection::appendHexData(StringRef HexData) {
370 assert((HexData.size() & 1) == 0);
371 while (!HexData.empty()) {
372 Data.push_back(checkedGetHex(HexData.take_front(2)));
373 HexData = HexData.drop_front(2);
374 }
375 Size = Data.size();
217376 }
218377
219378 void BinarySectionWriter::visit(const CompressedSection &Sec) {
18061965 return Error::success();
18071966 }
18081967
1968 bool IHexWriter::SectionCompare::operator()(const SectionBase *Lhs,
1969 const SectionBase *Rhs) const {
1970 return (sectionPhysicalAddr(Lhs) & 0xFFFFFFFFU) <
1971 (sectionPhysicalAddr(Rhs) & 0xFFFFFFFFU);
1972 }
1973
1974 uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
1975 IHexLineData HexData;
1976 uint8_t Data[4] = {};
1977 // We don't write entry point record if entry is zero.
1978 if (Obj.Entry == 0)
1979 return 0;
1980
1981 if (Obj.Entry <= 0xFFFFFU) {
1982 Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
1983 support::endian::write(&Data[2], static_cast(Obj.Entry),
1984 support::big);
1985 HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);
1986 } else {
1987 support::endian::write(Data, static_cast(Obj.Entry),
1988 support::big);
1989 HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);
1990 }
1991 memcpy(Buf, HexData.data(), HexData.size());
1992 return HexData.size();
1993 }
1994
1995 uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
1996 IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});
1997 memcpy(Buf, HexData.data(), HexData.size());
1998 return HexData.size();
1999 }
2000
2001 Error IHexWriter::write() {
2002 IHexSectionWriter Writer(Buf);
2003 // Write sections.
2004 for (const SectionBase *Sec : Sections)
2005 Sec->accept(Writer);
2006
2007 uint64_t Offset = Writer.getBufferOffset();
2008 // Write entry point address.
2009 Offset += writeEntryPointRecord(Buf.getBufferStart() + Offset);
2010 // Write EOF.
2011 Offset += writeEndOfFileRecord(Buf.getBufferStart() + Offset);
2012 assert(Offset == TotalSize);
2013 return Buf.commit();
2014 }
2015
2016 Error IHexWriter::checkSection(const SectionBase &Sec) {
2017 uint64_t Addr = sectionPhysicalAddr(&Sec);
2018 if (addressOverflows32bit(Addr) || addressOverflows32bit(Addr + Sec.Size - 1))
2019 return createStringError(
2020 errc::invalid_argument,
2021 "Section '%s' address range [%p, %p] is not 32 bit", Sec.Name.c_str(),
2022 Addr, Addr + Sec.Size - 1);
2023 return Error::success();
2024 }
2025
2026 Error IHexWriter::finalize() {
2027 bool UseSegments = false;
2028 auto ShouldWrite = [](const SectionBase &Sec) {
2029 return (Sec.Flags & ELF::SHF_ALLOC) && (Sec.Type != ELF::SHT_NOBITS);
2030 };
2031 auto IsInPtLoad = [](const SectionBase &Sec) {
2032 return Sec.ParentSegment && Sec.ParentSegment->Type == ELF::PT_LOAD;
2033 };
2034
2035 // We can't write 64-bit addresses.
2036 if (addressOverflows32bit(Obj.Entry))
2037 return createStringError(errc::invalid_argument,
2038 "Entry point address %p overflows 32 bits.",
2039 Obj.Entry);
2040
2041 // If any section we're to write has segment then we
2042 // switch to using physical addresses. Otherwise we
2043 // use section virtual address.
2044 for (auto &Section : Obj.sections())
2045 if (ShouldWrite(Section) && IsInPtLoad(Section)) {
2046 UseSegments = true;
2047 break;
2048 }
2049
2050 for (auto &Section : Obj.sections())
2051 if (ShouldWrite(Section) && (!UseSegments || IsInPtLoad(Section))) {
2052 if (Error E = checkSection(Section))
2053 return E;
2054 Sections.insert(&Section);
2055 }
2056
2057 IHexSectionWriterBase LengthCalc(Buf);
2058 for (const SectionBase *Sec : Sections)
2059 Sec->accept(LengthCalc);
2060
2061 // We need space to write section records + StartAddress record
2062 // (if start adress is not zero) + EndOfFile record.
2063 TotalSize = LengthCalc.getBufferOffset() +
2064 (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
2065 IHexRecord::getLineLength(0);
2066 if (Error E = Buf.allocate(TotalSize))
2067 return E;
2068 return Error::success();
2069 }
2070
18092071 template class ELFBuilder;
18102072 template class ELFBuilder;
18112073 template class ELFBuilder;
1616 #include "llvm/BinaryFormat/ELF.h"
1717 #include "llvm/MC/StringTableBuilder.h"
1818 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/Support/Errc.h"
1920 #include "llvm/Support/FileOutputBuffer.h"
2021 #include
2122 #include
167168
168169 #define MAKE_SEC_WRITER_FRIEND \
169170 friend class SectionWriter; \
171 friend class IHexSectionWriterBase; \
172 friend class IHexSectionWriter; \
170173 template friend class ELFSectionWriter; \
171174 template friend class ELFSectionSizer;
172175
185188 explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
186189 };
187190
191 using IHexLineData = SmallVector;
192
193 struct IHexRecord {
194 // Memory address of the record.
195 uint16_t Addr;
196 // Record type (see below).
197 uint16_t Type;
198 // Record data in hexadecimal form.
199 StringRef HexData;
200
201 // Helper method to get file length of the record
202 // including newline character
203 static size_t getLength(size_t DataSize) {
204 // :LLAAAATT[DD...DD]CC'
205 return DataSize * 2 + 11;
206 }
207
208 // Gets length of line in a file (getLength + CRLF).
209 static size_t getLineLength(size_t DataSize) {
210 return getLength(DataSize) + 2;
211 }
212
213 // Given type, address and data returns line which can
214 // be written to output file.
215 static IHexLineData getLine(uint8_t Type, uint16_t Addr,
216 ArrayRef Data);
217
218 // Calculates checksum of stringified record representation
219 // S must NOT contain leading ':' and trailing whitespace
220 // characters
221 static uint8_t getChecksum(StringRef S);
222
223 enum Type {
224 // Contains data and a 16-bit starting address for the data.
225 // The byte count specifies number of data bytes in the record.
226 Data = 0,
227 // Must occur exactly once per file in the last line of the file.
228 // The data field is empty (thus byte count is 00) and the address
229 // field is typically 0000.
230 EndOfFile = 1,
231 // The data field contains a 16-bit segment base address (thus byte
232 // count is always 02) compatible with 80x86 real mode addressing.
233 // The address field (typically 0000) is ignored. The segment address
234 // from the most recent 02 record is multiplied by 16 and added to each
235 // subsequent data record address to form the physical starting address
236 // for the data. This allows addressing up to one megabyte of address
237 // space.
238 SegmentAddr = 2,
239 // or 80x86 processors, specifies the initial content of the CS:IP
240 // registers. The address field is 0000, the byte count is always 04,
241 // the first two data bytes are the CS value, the latter two are the
242 // IP value.
243 StartAddr80x86 = 3,
244 // Allows for 32 bit addressing (up to 4GiB). The record's address field
245 // is ignored (typically 0000) and its byte count is always 02. The two
246 // data bytes (big endian) specify the upper 16 bits of the 32 bit
247 // absolute address for all subsequent type 00 records
248 ExtendedAddr = 4,
249 // The address field is 0000 (not used) and the byte count is always 04.
250 // The four data bytes represent a 32-bit address value. In the case of
251 // 80386 and higher CPUs, this address is loaded into the EIP register.
252 StartAddr = 5,
253 // We have no other valid types
254 InvalidType = 6
255 };
256 };
257
258 // Base class for IHexSectionWriter. This class implements writing algorithm,
259 // but doesn't actually write records. It is used for output buffer size
260 // calculation in IHexWriter::finalize.
261 class IHexSectionWriterBase : public BinarySectionWriter {
262 // 20-bit segment address
263 uint32_t SegmentAddr = 0;
264 // Extended linear address
265 uint32_t BaseAddr = 0;
266
267 // Write segment address corresponding to 'Addr'
268 uint64_t writeSegmentAddr(uint64_t Addr);
269 // Write extended linear (base) address corresponding to 'Addr'
270 uint64_t writeBaseAddr(uint64_t Addr);
271
272 protected:
273 // Offset in the output buffer
274 uint64_t Offset = 0;
275
276 void writeSection(const SectionBase *Sec, ArrayRef Data);
277 virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef Data);
278
279 public:
280 explicit IHexSectionWriterBase(Buffer &Buf) : BinarySectionWriter(Buf) {}
281
282 uint64_t getBufferOffset() const { return Offset; }
283 void visit(const Section &Sec) final;
284 void visit(const OwnedDataSection &Sec) final;
285 void visit(const StringTableSection &Sec) override;
286 void visit(const DynamicRelocationSection &Sec) final;
287 using BinarySectionWriter::visit;
288 };
289
290 // Real IHEX section writer
291 class IHexSectionWriter : public IHexSectionWriterBase {
292 public:
293 IHexSectionWriter(Buffer &Buf) : IHexSectionWriterBase(Buf) {}
294
295 void writeData(uint8_t Type, uint16_t Addr, ArrayRef Data) override;
296 void visit(const StringTableSection &Sec) override;
297 };
298
188299 class Writer {
189300 protected:
190301 Object &Obj;
242353 Error finalize() override;
243354 Error write() override;
244355 BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
356 };
357
358 class IHexWriter : public Writer {
359 struct SectionCompare {
360 bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const;
361 };
362
363 std::set Sections;
364 size_t TotalSize;
365
366 Error checkSection(const SectionBase &Sec);
367 uint64_t writeEntryPointRecord(uint8_t *Buf);
368 uint64_t writeEndOfFileRecord(uint8_t *Buf);
369
370 public:
371 ~IHexWriter() {}
372 Error finalize() override;
373 Error write() override;
374 IHexWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
245375 };
246376
247377 class SectionBase {
360490 OriginalOffset = std::numeric_limits::max();
361491 }
362492
493 OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
494 uint64_t SecOff) {
495 Name = SecName.str();
496 Type = ELF::SHT_PROGBITS;
497 Addr = SecAddr;
498 Flags = SecFlags;
499 OriginalOffset = SecOff;
500 }
501
502 void appendHexData(StringRef HexData);
363503 void accept(SectionVisitor &Sec) const override;
364504 void accept(MutableSectionVisitor &Visitor) override;
365505 };