llvm.org GIT mirror llvm / af8a28d
[llvm-objcopy] Implement IHEX reader This is the final part of IHEX format support in llvm-objcopy Differential revision: https://reviews.llvm.org/D62583 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363243 91177308-0d34-0410-b5e6-96231b3b80d8 Eugene Leviant 4 months ago
7 changed file(s) with 521 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
0 :020000021000EC
1 :08FFF8000001020304050607E5
2 :020000022000DC
3 :0300000008090AE2
4 :02000002F0000C
5 :08FFF800303132333435363765
6 :020000020000FC
7 :020000040010EA
8 :030000003839404C
9 :02000004001FDB
10 :08FFF8004041424344454647E5
11 :020000040020DA
12 :030000004849501C
13 :0400000300000000F9
14 :00000001FF
0 # Check section headers when converting from hex to ELF
1 # RUN: yaml2obj %p/Inputs/ihex-elf-sections.yaml -o %t
2 # RUN: llvm-objcopy -O ihex %t %t.hex
3 # RUN: llvm-objcopy -I ihex -O elf32-i386 %t.hex %t2
4 # RUN: llvm-readobj -section-headers %t2 | FileCheck %s
5
6 # Check section contents
7 # RUN: llvm-objcopy -O binary --only-section=.text %t %t.text
8 # RUN: llvm-objcopy -O binary --only-section=.sec1 %t2 %t2.sec1
9 # RUN: cmp %t.text %t2.sec1
10 # RUN: llvm-objcopy -O binary --only-section=.data %t %t.data
11 # RUN: llvm-objcopy -O binary --only-section=.sec2 %t2 %t2.sec2
12 # RUN: cmp %t.data %t2.sec2
13 # RUN: llvm-objcopy -O binary --only-section=.data2 %t %t.data2
14 # RUN: llvm-objcopy -O binary --only-section=.sec3 %t2 %t2.sec3
15 # RUN: cmp %t.data2 %t2.sec3
16 # RUN: llvm-objcopy -O binary --only-section=.data3 %t %t.data3
17 # RUN: llvm-objcopy -O binary --only-section=.sec4 %t2 %t2.sec4
18 # RUN: cmp %t.data3 %t2.sec4
19
20 # Check loading from raw hex file
21 # RUN: llvm-objcopy -I ihex -O elf32-i386 %p/Inputs/sections.hex %t-raw
22 # RUN: llvm-readobj -section-headers %t-raw | FileCheck %s --check-prefix=RAW
23
24 # Check section contents
25 # RUN: llvm-objcopy -O ihex --only-section=.sec1 %t-raw - | FileCheck %s --check-prefix=RAW-SEC1
26 # RUN: llvm-objcopy -O ihex --only-section=.sec2 %t-raw - | FileCheck %s --check-prefix=RAW-SEC2
27 # RUN: llvm-objcopy -O ihex --only-section=.sec3 %t-raw - | FileCheck %s --check-prefix=RAW-SEC3
28
29 # Check that line is trimmed from whitespace
30 # RUN: echo " :0100000001FE " | llvm-objcopy -I ihex -O elf64-x86-64 - - \
31 # RUN: | llvm-objcopy -O ihex - - | FileCheck %s --check-prefix=SPACES
32
33 # Check for various parsing errors
34 # 1. String too short
35 # RUN: echo "01000000FF" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_LENGTH
36
37 # 2. missing ':'
38 # RUN: echo "0100000000FF" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=MISSING_COLON
39
40 # 3. invalid charatcer
41 # RUN: echo ":01000000xF" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_CHAR
42
43 # 4. incorrect string length
44 # RUN: echo ":010000000000000F" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_LENGTH2
45
46 # 5. invalid type (06)
47 # RUN: echo ":00000006FA" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_TYPE
48
49 # 6. invalid checksum
50 # RUN: echo ":00000001FA" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_CKSUM
51
52 # 7. zero data length
53 # RUN: echo ":00010000FF" | not llvm-objcopy -I ihex - - 2>&1 | FileCheck %s --check-prefix=ZERO_DATA_LEN
54
55 # 8. Bad data length for '02' (SegmentAddr) record
56 # RUN: echo ":03000002000000FB" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_SEGADDR_LEN
57
58 # 9. Bad data length for '03' (StartAddr80x86) record
59 # RUN: echo ":03000003000000FA" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_STARTADDR_LEN
60
61 # 10. Bad data length for '05' (StartAddr) record
62 # RUN: echo ":03000005000000F8" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_STARTADDR_LEN
63
64 # 11. Address value for 'StartAddr80x86' is greater then 0xFFFFFU
65 # RUN: echo ":04000003FFFFFFFFFD" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_STARTADDR
66
67 # 12. Invalid extended address data size
68 # RUN: echo ":04000004FFFFFFFFFC" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_EXTADDR_LEN
69
70 # 13. no sections in the hex file
71 # a) try empty file:
72 # RUN: echo "" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=NO_SECTIONS
73 # b) EOF record should cancel processing further records. Not having any section data
74 # before EOF should trigger an error
75 # RUN: echo ":00000001FF" > %t-bad14.hex
76 # RUN: echo ":0100000001FE" >> %t-bad14.hex
77 # RUN: not llvm-objcopy -I ihex %t-bad14.hex %t-none 2>&1 | FileCheck %s --check-prefix=NO_SECTIONS
78
79 # CHECK: Index: 1
80 # CHECK-NEXT: Name: .sec1
81 # CHECK-NEXT: Type: SHT_PROGBITS (0x1)
82 # CHECK-NEXT: Flags [ (0x3)
83 # CHECK-NEXT: SHF_ALLOC (0x2)
84 # CHECK-NEXT: SHF_WRITE (0x1)
85 # CHECK-NEXT: ]
86 # CHECK-NEXT: Address: 0x0
87 # CHECK-NEXT: Offset: 0x34
88 # CHECK-NEXT: Size: 21
89 # CHECK-NEXT: Link: 0
90 # CHECK-NEXT: Info: 0
91 # CHECK-NEXT: AddressAlignment: 1
92 # CHECK-NEXT: EntrySize: 0
93
94 # CHECK: Index: 2
95 # CHECK-NEXT: Name: .sec2
96 # CHECK-NEXT: Type: SHT_PROGBITS (0x1)
97 # CHECK-NEXT: Flags [ (0x3)
98 # CHECK-NEXT: SHF_ALLOC (0x2)
99 # CHECK-NEXT: SHF_WRITE (0x1)
100 # CHECK-NEXT: ]
101 # CHECK-NEXT: Address: 0xFFF8
102 # CHECK-NEXT: Offset: 0x49
103 # CHECK-NEXT: Size: 11
104 # CHECK-NEXT: Link: 0
105 # CHECK-NEXT: Info: 0
106 # CHECK-NEXT: AddressAlignment: 1
107 # CHECK-NEXT: EntrySize: 0
108
109 # CHECK: Index: 3
110 # CHECK-NEXT: Name: .sec3
111 # CHECK-NEXT: Type: SHT_PROGBITS (0x1)
112 # CHECK-NEXT: Flags [ (0x3)
113 # CHECK-NEXT: SHF_ALLOC (0x2)
114 # CHECK-NEXT: SHF_WRITE (0x1)
115 # CHECK-NEXT: ]
116 # CHECK-NEXT: Address: 0x10100
117 # CHECK-NEXT: Offset: 0x54
118 # CHECK-NEXT: Size: 4
119 # CHECK-NEXT: Link: 0
120 # CHECK-NEXT: Info: 0
121 # CHECK-NEXT: AddressAlignment: 1
122 # CHECK-NEXT: EntrySize: 0
123
124 # CHECK: Index: 4
125 # CHECK-NEXT: Name: .sec4
126 # CHECK-NEXT: Type: SHT_PROGBITS (0x1)
127 # CHECK-NEXT: Flags [ (0x3)
128 # CHECK-NEXT: SHF_ALLOC (0x2)
129 # CHECK-NEXT: SHF_WRITE (0x1)
130 # CHECK-NEXT: ]
131 # CHECK-NEXT: Address: 0x10FFF8
132 # CHECK-NEXT: Offset: 0x58
133 # CHECK-NEXT: Size: 11
134 # CHECK-NEXT: Link: 0
135 # CHECK-NEXT: Info: 0
136 # CHECK-NEXT: AddressAlignment: 1
137 # CHECK-NEXT: EntrySize: 0
138
139 # RAW: Index: 1
140 # RAW-NEXT: Name: .sec1
141 # RAW-NEXT: Type: SHT_PROGBITS (0x1)
142 # RAW-NEXT: Flags [ (0x3)
143 # RAW-NEXT: SHF_ALLOC (0x2)
144 # RAW-NEXT: SHF_WRITE (0x1)
145 # RAW-NEXT: ]
146 # RAW-NEXT: Address: 0x1FFF8
147 # RAW-NEXT: Offset: 0x34
148 # RAW-NEXT: Size: 11
149
150 # RAW: Index: 2
151 # RAW-NEXT: Name: .sec2
152 # RAW-NEXT: Type: SHT_PROGBITS (0x1)
153 # RAW-NEXT: Flags [ (0x3)
154 # RAW-NEXT: SHF_ALLOC (0x2)
155 # RAW-NEXT: SHF_WRITE (0x1)
156 # RAW-NEXT: ]
157 # RAW-NEXT: Address: 0xFFFF8
158 # RAW-NEXT: Offset: 0x3F
159 # RAW-NEXT: Size: 11
160
161 # RAW: Index: 3
162 # RAW-NEXT: Name: .sec3
163 # RAW-NEXT: Type: SHT_PROGBITS (0x1)
164 # RAW-NEXT: Flags [ (0x3)
165 # RAW-NEXT: SHF_ALLOC (0x2)
166 # RAW-NEXT: SHF_WRITE (0x1)
167 # RAW-NEXT: ]
168 # RAW-NEXT: Address: 0x1FFFF8
169 # RAW-NEXT: Offset: 0x4A
170 # RAW-NEXT: Size: 11
171
172 # RAW-SEC1: :020000021000EC
173 # RAW-SEC1-NEXT: :08FFF8000001020304050607E5
174 # RAW-SEC1-NEXT: :020000022000DC
175 # RAW-SEC1-NEXT: :0300000008090AE2
176
177 # RAW-SEC2: :02000002F0000C
178 # RAW-SEC2-NEXT: :08FFF800303132333435363765
179 # RAW-SEC2-NEXT: :020000020000FC
180 # RAW-SEC2-NEXT: :020000040010EA
181 # RAW-SEC2-NEXT: :030000003839404C
182
183 # RAW-SEC3: :02000004001FDB
184 # RAW-SEC3-NEXT: :08FFF8004041424344454647E5
185 # RAW-SEC3-NEXT: :020000040020DA
186 # RAW-SEC3-NEXT: :030000004849501C
187
188 # SPACES: :0100000001FE
189 # SPACES-NEXT: :00000001FF
190
191 # BAD_LENGTH: error: '{{.*}}': line 1: line is too short: 10 chars
192 # MISSING_COLON: error: '{{.*}}': line 1: missing ':' in the beginning of line
193 # BAD_CHAR: error: '{{.*}}': line 1: invalid character at position 10
194 # BAD_LENGTH2: error: '{{.*}}': line 1: invalid line length 17 (should be 13)
195 # BAD_TYPE: error: '{{.*}}': line 1: unknown record type: 6
196 # BAD_CKSUM: error: '{{.*}}': line 1: incorrect checksum
197 # ZERO_DATA_LEN: error: '{{.*}}': line 1: zero data length is not allowed for data records
198 # BAD_SEGADDR_LEN: error: '{{.*}}': line 1: segment address data should be 2 bytes in size
199 # BAD_STARTADDR_LEN: error: '{{.*}}': line 1: start address data should be 4 bytes in size
200 # BAD_STARTADDR: error: '{{.*}}': line 1: start address exceeds 20 bit for 80x86
201 # BAD_EXTADDR_LEN: error: '{{.*}}': line 1: extended address data should be 2 bytes in size
202 # NO_SECTIONS: error: '{{.*}}': no sections
740740 return Writer->write();
741741 }
742742
743 Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
744 Buffer &Out) {
745 IHexReader Reader(&In);
746 std::unique_ptr Obj = Reader.create();
747 const ElfType OutputElfType =
748 getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch));
749 if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType))
750 return E;
751 return writeOutput(Config, *Obj, Out, OutputElfType);
752 }
753
743754 Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
744755 Buffer &Out) {
745756 BinaryReader Reader(Config.BinaryArch, &In);
2121 class Buffer;
2222
2323 namespace elf {
24 Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
25 Buffer &Out);
2426 Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
2527 Buffer &Out);
2628 Error executeObjcopyOnBinary(const CopyConfig &Config,
202202 *Iter++ = '\n';
203203 assert(Iter == Line.end());
204204 return Line;
205 }
206
207 static Error checkRecord(const IHexRecord &R) {
208 switch (R.Type) {
209 case IHexRecord::Data:
210 if (R.HexData.size() == 0)
211 return createStringError(
212 errc::invalid_argument,
213 "zero data length is not allowed for data records");
214 break;
215 case IHexRecord::EndOfFile:
216 break;
217 case IHexRecord::SegmentAddr:
218 // 20-bit segment address. Data length must be 2 bytes
219 // (4 bytes in hex)
220 if (R.HexData.size() != 4)
221 return createStringError(
222 errc::invalid_argument,
223 "segment address data should be 2 bytes in size");
224 break;
225 case IHexRecord::StartAddr80x86:
226 case IHexRecord::StartAddr:
227 if (R.HexData.size() != 8)
228 return createStringError(errc::invalid_argument,
229 "start address data should be 4 bytes in size");
230 // According to Intel HEX specification '03' record
231 // only specifies the code address within the 20-bit
232 // segmented address space of the 8086/80186. This
233 // means 12 high order bits should be zeroes.
234 if (R.Type == IHexRecord::StartAddr80x86 &&
235 R.HexData.take_front(3) != "000")
236 return createStringError(errc::invalid_argument,
237 "start address exceeds 20 bit for 80x86");
238 break;
239 case IHexRecord::ExtendedAddr:
240 // 16-31 bits of linear base address
241 if (R.HexData.size() != 4)
242 return createStringError(
243 errc::invalid_argument,
244 "extended address data should be 2 bytes in size");
245 break;
246 default:
247 // Unknown record type
248 return createStringError(errc::invalid_argument, "unknown record type: %u",
249 static_cast(R.Type));
250 }
251 return Error::success();
252 }
253
254 // Checks that IHEX line contains valid characters.
255 // This allows converting hexadecimal data to integers
256 // without extra verification.
257 static Error checkChars(StringRef Line) {
258 assert(!Line.empty());
259 if (Line[0] != ':')
260 return createStringError(errc::invalid_argument,
261 "missing ':' in the beginning of line.");
262
263 for (size_t Pos = 1; Pos < Line.size(); ++Pos)
264 if (hexDigitValue(Line[Pos]) == -1U)
265 return createStringError(errc::invalid_argument,
266 "invalid character at position %zu.", Pos + 1);
267 return Error::success();
268 }
269
270 Expected IHexRecord::parse(StringRef Line) {
271 assert(!Line.empty());
272
273 // ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'
274 if (Line.size() < 11)
275 return createStringError(errc::invalid_argument,
276 "line is too short: %zu chars.", Line.size());
277
278 if (Error E = checkChars(Line))
279 return std::move(E);
280
281 IHexRecord Rec;
282 size_t DataLen = checkedGetHex(Line.substr(1, 2));
283 if (Line.size() != getLength(DataLen))
284 return createStringError(errc::invalid_argument,
285 "invalid line length %zu (should be %zu)",
286 Line.size(), getLength(DataLen));
287
288 Rec.Addr = checkedGetHex(Line.substr(3, 4));
289 Rec.Type = checkedGetHex(Line.substr(7, 2));
290 Rec.HexData = Line.substr(9, DataLen * 2);
291
292 if (getChecksum(Line.drop_front(1)) != 0)
293 return createStringError(errc::invalid_argument, "incorrect checksum.");
294 if (Error E = checkRecord(Rec))
295 return std::move(E);
296 return Rec;
205297 }
206298
207299 static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
828920 }
829921
830922 void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
831 Visitor.visit(*this);
832 }
833
834 Error DynamicRelocationSection::removeSectionReferences(
835 bool AllowBrokenLinks, function_ref ToRemove) {
836 if (ToRemove(Symbols)) {
837 if (!AllowBrokenLinks)
838 return createStringError(
839 llvm::errc::invalid_argument,
923 Visitor.visit(*this);
924 }
925
926 Error DynamicRelocationSection::removeSectionReferences(
927 bool AllowBrokenLinks, function_ref ToRemove) {
928 if (ToRemove(Symbols)) {
929 if (!AllowBrokenLinks)
930 return createStringError(
931 llvm::errc::invalid_argument,
840932 "symbol table '%s' cannot be removed because it is "
841933 "referenced by the relocation section '%s'",
842 Symbols->Name.data(), this->Name.data());
843 Symbols = nullptr;
844 }
845
846 // SecToApplyRel contains a section referenced by sh_info field. It keeps
847 // a section to which the relocation section applies. When we remove any
848 // sections we also remove their relocation sections. Since we do that much
849 // earlier, this assert should never be triggered.
850 assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
851 return Error::success();
852 }
853
854 Error Section::removeSectionReferences(bool AllowBrokenDependency,
855 function_ref ToRemove) {
856 if (ToRemove(LinkSection)) {
934 Symbols->Name.data(), this->Name.data());
935 Symbols = nullptr;
936 }
937
938 // SecToApplyRel contains a section referenced by sh_info field. It keeps
939 // a section to which the relocation section applies. When we remove any
940 // sections we also remove their relocation sections. Since we do that much
941 // earlier, this assert should never be triggered.
942 assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
943 return Error::success();
944 }
945
946 Error Section::removeSectionReferences(
947 bool AllowBrokenDependency,
948 function_ref ToRemove) {
949 if (ToRemove(LinkSection)) {
857950 if (!AllowBrokenDependency)
858951 return createStringError(llvm::errc::invalid_argument,
859952 "section '%s' cannot be removed because it is "
10121105 return A->Index < B->Index;
10131106 }
10141107
1015 void BinaryELFBuilder::initFileHeader() {
1108 void BasicELFBuilder::initFileHeader() {
10161109 Obj->Flags = 0x0;
10171110 Obj->Type = ET_REL;
10181111 Obj->OSABI = ELFOSABI_NONE;
10221115 Obj->Version = 1;
10231116 }
10241117
1025 void BinaryELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
1026
1027 StringTableSection *BinaryELFBuilder::addStrTab() {
1118 void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
1119
1120 StringTableSection *BasicELFBuilder::addStrTab() {
10281121 auto &StrTab = Obj->addSection();
10291122 StrTab.Name = ".strtab";
10301123
10321125 return &StrTab;
10331126 }
10341127
1035 SymbolTableSection *BinaryELFBuilder::addSymTab(StringTableSection *StrTab) {
1128 SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
10361129 auto &SymTab = Obj->addSection();
10371130
10381131 SymTab.Name = ".symtab";
10431136
10441137 Obj->SymbolTable = &SymTab;
10451138 return &SymTab;
1139 }
1140
1141 void BasicELFBuilder::initSections() {
1142 for (auto &Section : Obj->sections())
1143 Section.initialize(Obj->sections());
10461144 }
10471145
10481146 void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
10681166 /*Value=*/DataSection.Size, STV_DEFAULT, SHN_ABS, 0);
10691167 }
10701168
1071 void BinaryELFBuilder::initSections() {
1072 for (SectionBase &Section : Obj->sections())
1073 Section.initialize(Obj->sections());
1074 }
1075
10761169 std::unique_ptr BinaryELFBuilder::build() {
10771170 initFileHeader();
10781171 initHeaderSegment();
10801173 SymbolTableSection *SymTab = addSymTab(addStrTab());
10811174 initSections();
10821175 addData(SymTab);
1176
1177 return std::move(Obj);
1178 }
1179
1180 // Adds sections from IHEX data file. Data should have been
1181 // fully validated by this time.
1182 void IHexELFBuilder::addDataSections() {
1183 OwnedDataSection *Section = nullptr;
1184 uint64_t SegmentAddr = 0, BaseAddr = 0;
1185 uint32_t SecNo = 1;
1186
1187 for (const IHexRecord &R : Records) {
1188 uint64_t RecAddr;
1189 switch (R.Type) {
1190 case IHexRecord::Data:
1191 // Ignore empty data records
1192 if (R.HexData.empty())
1193 continue;
1194 RecAddr = R.Addr + SegmentAddr + BaseAddr;
1195 if (!Section || Section->Addr + Section->Size != RecAddr)
1196 // OriginalOffset field is only used to sort section properly, so
1197 // instead of keeping track of real offset in IHEX file, we use
1198 // section number.
1199 Section = &Obj->addSection(
1200 ".sec" + std::to_string(SecNo++), RecAddr,
1201 ELF::SHF_ALLOC | ELF::SHF_WRITE, SecNo);
1202 Section->appendHexData(R.HexData);
1203 break;
1204 case IHexRecord::EndOfFile:
1205 break;
1206 case IHexRecord::SegmentAddr:
1207 // 20-bit segment address.
1208 SegmentAddr = checkedGetHex(R.HexData) << 4;
1209 break;
1210 case IHexRecord::StartAddr80x86:
1211 case IHexRecord::StartAddr:
1212 Obj->Entry = checkedGetHex(R.HexData);
1213 assert(Obj->Entry <= 0xFFFFFU);
1214 break;
1215 case IHexRecord::ExtendedAddr:
1216 // 16-31 bits of linear base address
1217 BaseAddr = checkedGetHex(R.HexData) << 16;
1218 break;
1219 default:
1220 llvm_unreachable("unknown record type");
1221 }
1222 }
1223 }
1224
1225 std::unique_ptr IHexELFBuilder::build() {
1226 initFileHeader();
1227 initHeaderSegment();
1228 StringTableSection *StrTab = addStrTab();
1229 addSymTab(StrTab);
1230 initSections();
1231 addDataSections();
10831232
10841233 return std::move(Obj);
10851234 }
14601609
14611610 std::unique_ptr BinaryReader::create() const {
14621611 return BinaryELFBuilder(MInfo.EMachine, MemBuf).build();
1612 }
1613
1614 Expected> IHexReader::parse() const {
1615 SmallVector Lines;
1616 std::vector Records;
1617 bool HasSections = false;
1618
1619 MemBuf->getBuffer().split(Lines, '\n');
1620 Records.reserve(Lines.size());
1621 for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
1622 StringRef Line = Lines[LineNo - 1].trim();
1623 if (Line.empty())
1624 continue;
1625
1626 Expected R = IHexRecord::parse(Line);
1627 if (!R)
1628 return parseError(LineNo, R.takeError());
1629 if (R->Type == IHexRecord::EndOfFile)
1630 break;
1631 HasSections |= (R->Type == IHexRecord::Data);
1632 Records.push_back(*R);
1633 }
1634 if (!HasSections)
1635 return parseError(-1U, "no sections");
1636
1637 return std::move(Records);
1638 }
1639
1640 std::unique_ptr IHexReader::create() const {
1641 std::vector Records = unwrapOrError(parse());
1642 return IHexELFBuilder(Records).build();
14631643 }
14641644
14651645 std::unique_ptr ELFReader::create() const {
214214 // be written to output file.
215215 static IHexLineData getLine(uint8_t Type, uint16_t Addr,
216216 ArrayRef Data);
217
218 // Parses the line and returns record if possible.
219 // Line should be trimmed from whitespace characters.
220 static Expected parse(StringRef Line);
217221
218222 // Calculates checksum of stringified record representation
219223 // S must NOT contain leading ':' and trailing whitespace
820824
821825 public:
822826 explicit DynamicRelocationSection(ArrayRef Data) : Contents(Data) {}
823
824 void accept(SectionVisitor &) const override;
825 void accept(MutableSectionVisitor &Visitor) override;
826 Error removeSectionReferences(
827 bool AllowBrokenLinks,
828 function_ref ToRemove) override;
829
830 static bool classof(const SectionBase *S) {
831 if (!(S->Flags & ELF::SHF_ALLOC))
827
828 void accept(SectionVisitor &) const override;
829 void accept(MutableSectionVisitor &Visitor) override;
830 Error removeSectionReferences(
831 bool AllowBrokenLinks,
832 function_ref ToRemove) override;
833
834 static bool classof(const SectionBase *S) {
835 if (!(S->Flags & ELF::SHF_ALLOC))
832836 return false;
833837 return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
834838 }
861865 using object::ELFObjectFile;
862866 using object::OwningBinary;
863867
864 class BinaryELFBuilder {
868 class BasicELFBuilder {
869 protected:
865870 uint16_t EMachine;
866 MemoryBuffer *MemBuf;
867871 std::unique_ptr Obj;
868872
869873 void initFileHeader();
870874 void initHeaderSegment();
871875 StringTableSection *addStrTab();
872876 SymbolTableSection *addSymTab(StringTableSection *StrTab);
877 void initSections();
878
879 public:
880 BasicELFBuilder(uint16_t EM)
881 : EMachine(EM), Obj(llvm::make_unique()) {}
882 };
883
884 class BinaryELFBuilder : public BasicELFBuilder {
885 MemoryBuffer *MemBuf;
873886 void addData(SymbolTableSection *SymTab);
874 void initSections();
875887
876888 public:
877889 BinaryELFBuilder(uint16_t EM, MemoryBuffer *MB)
878 : EMachine(EM), MemBuf(MB), Obj(llvm::make_unique()) {}
890 : BasicELFBuilder(EM), MemBuf(MB) {}
891
892 std::unique_ptr build();
893 };
894
895 class IHexELFBuilder : public BasicELFBuilder {
896 const std::vector &Records;
897
898 void addDataSections();
899
900 public:
901 IHexELFBuilder(const std::vector &Records)
902 : BasicELFBuilder(ELF::EM_386), Records(Records) {}
879903
880904 std::unique_ptr build();
881905 };
916940 public:
917941 BinaryReader(const MachineInfo &MI, MemoryBuffer *MB)
918942 : MInfo(MI), MemBuf(MB) {}
943 std::unique_ptr create() const override;
944 };
945
946 class IHexReader : public Reader {
947 MemoryBuffer *MemBuf;
948
949 Expected> parse() const;
950 Error parseError(size_t LineNo, Error E) const {
951 return LineNo == -1U
952 ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
953 : createFileError(MemBuf->getBufferIdentifier(), LineNo,
954 std::move(E));
955 }
956 template
957 Error parseError(size_t LineNo, char const *Fmt, const Ts &... Vals) const {
958 Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
959 return parseError(LineNo, std::move(E));
960 }
961
962 public:
963 IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
964
919965 std::unique_ptr create() const override;
920966 };
921967
122122 return Error::success();
123123 }
124124
125 /// The function executeObjcopyOnIHex does the dispatch based on the format
126 /// of the output specified by the command line options.
127 static Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
128 Buffer &Out) {
129 // TODO: support output formats other than ELF.
130 return elf::executeObjcopyOnIHex(Config, In, Out);
131 }
132
125133 /// The function executeObjcopyOnRawBinary does the dispatch based on the format
126134 /// of the output specified by the command line options.
127135 static Error executeObjcopyOnRawBinary(const CopyConfig &Config,
209217 if (auto EC = sys::fs::status(Config.InputFilename, Stat))
210218 return createFileError(Config.InputFilename, EC);
211219
212 if (Config.InputFormat == "binary") {
213 auto BufOrErr = MemoryBuffer::getFile(Config.InputFilename);
220 typedef Error (*ProcessRawFn)(const CopyConfig &, MemoryBuffer &, Buffer &);
221 auto ProcessRaw = StringSwitch(Config.InputFormat)
222 .Case("binary", executeObjcopyOnRawBinary)
223 .Case("ihex", executeObjcopyOnIHex)
224 .Default(nullptr);
225
226 if (ProcessRaw) {
227 auto BufOrErr = MemoryBuffer::getFileOrSTDIN(Config.InputFilename);
214228 if (!BufOrErr)
215229 return createFileError(Config.InputFilename, BufOrErr.getError());
216230 FileBuffer FB(Config.OutputFilename);
217 if (Error E = executeObjcopyOnRawBinary(Config, *BufOrErr->get(), FB))
231 if (Error E = ProcessRaw(Config, *BufOrErr->get(), FB))
218232 return E;
219233 } else {
220234 Expected> BinaryOrErr =