Skip to content

Commit

Permalink
[llvm-objcopy] Implement IHEX reader
Browse files Browse the repository at this point in the history
This is the final part of IHEX format support in llvm-objcopy
Differential revision: https://reviews.llvm.org/D62583

llvm-svn: 363243
  • Loading branch information
eleviant committed Jun 13, 2019
1 parent 95a9ee5 commit 86b7f86
Show file tree
Hide file tree
Showing 7 changed files with 520 additions and 49 deletions.
15 changes: 15 additions & 0 deletions llvm/test/tools/llvm-objcopy/ELF/Inputs/sections.hex
@@ -0,0 +1,15 @@
:020000021000EC
:08FFF8000001020304050607E5
:020000022000DC
:0300000008090AE2
:02000002F0000C
:08FFF800303132333435363765
:020000020000FC
:020000040010EA
:030000003839404C
:02000004001FDB
:08FFF8004041424344454647E5
:020000040020DA
:030000004849501C
:0400000300000000F9
:00000001FF
203 changes: 203 additions & 0 deletions llvm/test/tools/llvm-objcopy/ELF/ihex-reader.test
@@ -0,0 +1,203 @@
# Check section headers when converting from hex to ELF
# RUN: yaml2obj %p/Inputs/ihex-elf-sections.yaml -o %t
# RUN: llvm-objcopy -O ihex %t %t.hex
# RUN: llvm-objcopy -I ihex -O elf32-i386 %t.hex %t2
# RUN: llvm-readobj -section-headers %t2 | FileCheck %s

# Check section contents
# RUN: llvm-objcopy -O binary --only-section=.text %t %t.text
# RUN: llvm-objcopy -O binary --only-section=.sec1 %t2 %t2.sec1
# RUN: cmp %t.text %t2.sec1
# RUN: llvm-objcopy -O binary --only-section=.data %t %t.data
# RUN: llvm-objcopy -O binary --only-section=.sec2 %t2 %t2.sec2
# RUN: cmp %t.data %t2.sec2
# RUN: llvm-objcopy -O binary --only-section=.data2 %t %t.data2
# RUN: llvm-objcopy -O binary --only-section=.sec3 %t2 %t2.sec3
# RUN: cmp %t.data2 %t2.sec3
# RUN: llvm-objcopy -O binary --only-section=.data3 %t %t.data3
# RUN: llvm-objcopy -O binary --only-section=.sec4 %t2 %t2.sec4
# RUN: cmp %t.data3 %t2.sec4

# Check loading from raw hex file
# RUN: llvm-objcopy -I ihex -O elf32-i386 %p/Inputs/sections.hex %t-raw
# RUN: llvm-readobj -section-headers %t-raw | FileCheck %s --check-prefix=RAW

# Check section contents
# RUN: llvm-objcopy -O ihex --only-section=.sec1 %t-raw - | FileCheck %s --check-prefix=RAW-SEC1
# RUN: llvm-objcopy -O ihex --only-section=.sec2 %t-raw - | FileCheck %s --check-prefix=RAW-SEC2
# RUN: llvm-objcopy -O ihex --only-section=.sec3 %t-raw - | FileCheck %s --check-prefix=RAW-SEC3

# Check that line is trimmed from whitespace
# RUN: echo " :0100000001FE " | llvm-objcopy -I ihex -O elf64-x86-64 - - \
# RUN: | llvm-objcopy -O ihex - - | FileCheck %s --check-prefix=SPACES

# Check for various parsing errors
# 1. String too short
# RUN: echo "01000000FF" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_LENGTH

# 2. missing ':'
# RUN: echo "0100000000FF" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=MISSING_COLON

# 3. invalid charatcer
# RUN: echo ":01000000xF" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_CHAR

# 4. incorrect string length
# RUN: echo ":010000000000000F" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_LENGTH2

# 5. invalid type (06)
# RUN: echo ":00000006FA" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_TYPE

# 6. invalid checksum
# RUN: echo ":00000001FA" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_CKSUM

# 7. zero data length
# RUN: echo ":00010000FF" | not llvm-objcopy -I ihex - - 2>&1 | FileCheck %s --check-prefix=ZERO_DATA_LEN

# 8. Bad data length for '02' (SegmentAddr) record
# RUN: echo ":03000002000000FB" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_SEGADDR_LEN

# 9. Bad data length for '03' (StartAddr80x86) record
# RUN: echo ":03000003000000FA" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_STARTADDR_LEN

# 10. Bad data length for '05' (StartAddr) record
# RUN: echo ":03000005000000F8" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_STARTADDR_LEN

# 11. Address value for 'StartAddr80x86' is greater then 0xFFFFFU
# RUN: echo ":04000003FFFFFFFFFD" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_STARTADDR

# 12. Invalid extended address data size
# RUN: echo ":04000004FFFFFFFFFC" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=BAD_EXTADDR_LEN

# 13. no sections in the hex file
# a) try empty file:
# RUN: echo "" | not llvm-objcopy -I ihex -O elf32-i386 - - 2>&1 | FileCheck %s --check-prefix=NO_SECTIONS
# b) EOF record should cancel processing further records. Not having any section data
# before EOF should trigger an error
# RUN: echo ":00000001FF" > %t-bad14.hex
# RUN: echo ":0100000001FE" >> %t-bad14.hex
# RUN: not llvm-objcopy -I ihex %t-bad14.hex %t-none 2>&1 | FileCheck %s --check-prefix=NO_SECTIONS

# CHECK: Index: 1
# CHECK-NEXT: Name: .sec1
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
# CHECK-NEXT: Offset: 0x34
# CHECK-NEXT: Size: 21
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 1
# CHECK-NEXT: EntrySize: 0

# CHECK: Index: 2
# CHECK-NEXT: Name: .sec2
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0xFFF8
# CHECK-NEXT: Offset: 0x49
# CHECK-NEXT: Size: 11
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 1
# CHECK-NEXT: EntrySize: 0

# CHECK: Index: 3
# CHECK-NEXT: Name: .sec3
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x10100
# CHECK-NEXT: Offset: 0x54
# CHECK-NEXT: Size: 4
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 1
# CHECK-NEXT: EntrySize: 0

# CHECK: Index: 4
# CHECK-NEXT: Name: .sec4
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x10FFF8
# CHECK-NEXT: Offset: 0x58
# CHECK-NEXT: Size: 11
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 1
# CHECK-NEXT: EntrySize: 0

# RAW: Index: 1
# RAW-NEXT: Name: .sec1
# RAW-NEXT: Type: SHT_PROGBITS (0x1)
# RAW-NEXT: Flags [ (0x3)
# RAW-NEXT: SHF_ALLOC (0x2)
# RAW-NEXT: SHF_WRITE (0x1)
# RAW-NEXT: ]
# RAW-NEXT: Address: 0x1FFF8
# RAW-NEXT: Offset: 0x34
# RAW-NEXT: Size: 11

# RAW: Index: 2
# RAW-NEXT: Name: .sec2
# RAW-NEXT: Type: SHT_PROGBITS (0x1)
# RAW-NEXT: Flags [ (0x3)
# RAW-NEXT: SHF_ALLOC (0x2)
# RAW-NEXT: SHF_WRITE (0x1)
# RAW-NEXT: ]
# RAW-NEXT: Address: 0xFFFF8
# RAW-NEXT: Offset: 0x3F
# RAW-NEXT: Size: 11

# RAW: Index: 3
# RAW-NEXT: Name: .sec3
# RAW-NEXT: Type: SHT_PROGBITS (0x1)
# RAW-NEXT: Flags [ (0x3)
# RAW-NEXT: SHF_ALLOC (0x2)
# RAW-NEXT: SHF_WRITE (0x1)
# RAW-NEXT: ]
# RAW-NEXT: Address: 0x1FFFF8
# RAW-NEXT: Offset: 0x4A
# RAW-NEXT: Size: 11

# RAW-SEC1: :020000021000EC
# RAW-SEC1-NEXT: :08FFF8000001020304050607E5
# RAW-SEC1-NEXT: :020000022000DC
# RAW-SEC1-NEXT: :0300000008090AE2

# RAW-SEC2: :02000002F0000C
# RAW-SEC2-NEXT: :08FFF800303132333435363765
# RAW-SEC2-NEXT: :020000020000FC
# RAW-SEC2-NEXT: :020000040010EA
# RAW-SEC2-NEXT: :030000003839404C

# RAW-SEC3: :02000004001FDB
# RAW-SEC3-NEXT: :08FFF8004041424344454647E5
# RAW-SEC3-NEXT: :020000040020DA
# RAW-SEC3-NEXT: :030000004849501C

# SPACES: :0100000001FE
# SPACES-NEXT: :00000001FF

# BAD_LENGTH: error: '{{.*}}': line 1: line is too short: 10 chars
# MISSING_COLON: error: '{{.*}}': line 1: missing ':' in the beginning of line
# BAD_CHAR: error: '{{.*}}': line 1: invalid character at position 10
# BAD_LENGTH2: error: '{{.*}}': line 1: invalid line length 17 (should be 13)
# BAD_TYPE: error: '{{.*}}': line 1: unknown record type: 6
# BAD_CKSUM: error: '{{.*}}': line 1: incorrect checksum
# ZERO_DATA_LEN: error: '{{.*}}': line 1: zero data length is not allowed for data records
# BAD_SEGADDR_LEN: error: '{{.*}}': line 1: segment address data should be 2 bytes in size
# BAD_STARTADDR_LEN: error: '{{.*}}': line 1: start address data should be 4 bytes in size
# BAD_STARTADDR: error: '{{.*}}': line 1: start address exceeds 20 bit for 80x86
# BAD_EXTADDR_LEN: error: '{{.*}}': line 1: extended address data should be 2 bytes in size
# NO_SECTIONS: error: '{{.*}}': no sections
11 changes: 11 additions & 0 deletions llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
Expand Up @@ -741,6 +741,17 @@ static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out,
return Writer->write();
}

Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
Buffer &Out) {
IHexReader Reader(&In);
std::unique_ptr<Object> Obj = Reader.create();
const ElfType OutputElfType =
getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch));
if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType))
return E;
return writeOutput(Config, *Obj, Out, OutputElfType);
}

Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
Buffer &Out) {
BinaryReader Reader(Config.BinaryArch, &In);
Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h
Expand Up @@ -22,6 +22,8 @@ struct CopyConfig;
class Buffer;

namespace elf {
Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
Buffer &Out);
Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
Buffer &Out);
Error executeObjcopyOnBinary(const CopyConfig &Config,
Expand Down

0 comments on commit 86b7f86

Please sign in to comment.