The elf and ihx outputs differ when converted to binary.
There are lots of prepended 0x00 bytes in the elf and the alignment is incorrect.
example:
echo -e "int main() { }\n" > main.c
sdcc -mstm8 --std-sdcc11 -c main.c -o main.c.rel
sdcc -mstm8 --out-fmt-elf main.c.rel -o out.elf
objcopy -I elf32-big -O binary out.elf out.elf.bin
sdcc -mstm8 --out-fmt-ihx main.c.rel -o out.ihx
objcopy -I ihex -O binary out.ihx out.ihx.bin
readelf -S out.elf
hexdump -C out.elf.bin | head
cat out.ihx | head
hexdump -C out.ihx.bin | head
main.c:1: warning 59: function 'main' must return value
There are 9 section headers, starting at offset 0x214:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] SSEG PROGBITS 00000001 000034 000001 00 A 0 0 0
[ 2] HOME PROGBITS 00008000 000035 000007 00 A 0 0 0
[ 3] GSINIT PROGBITS 00008007 00003c 00001a 00 A 0 0 0
[ 4] GSFINAL PROGBITS 00008021 000056 000003 00 A 0 0 0
[ 5] CODE PROGBITS 00008024 000059 000001 00 A 0 0 0
[ 6] .symtab SYMTAB 00000000 00005a 000090 10 7 1 0
[ 7] .strtab STRTAB 00000000 0000ea 000051 00 0 0 0
[ 8] .shstrtab STRTAB 00000000 00013b 000039 00 0 0 0
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00007ff0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 |................|
00008000 00 80 07 cc 80 24 ae 00 00 27 07 72 4f 00 00 5a |.....$...'.rO..Z|
00008010 26 f9 ae 00 00 27 09 d6 80 23 d7 00 00 5a 26 f7 |&....'...#...Z&.|
00008020 cc 80 04 81 |....|
00008024
:048000008200800773
:1D800700AE00002707724F00005A26F9AE00002709D68023D700005A26F7CC800451
:03800400CC802409
:0180240081DA
:00000001FF
00000000 82 00 80 07 cc 80 24 ae 00 00 27 07 72 4f 00 00 |......$...'.rO..|
00000010 5a 26 f9 ae 00 00 27 09 d6 80 23 d7 00 00 5a 26 |Z&....'...#...Z&|
00000020 f7 cc 80 04 81 |.....|
00000025
To me it looks like objcopy is doing it wrong reading both files.
* Readelf tells the code starts at 0x8000 although it seems wrong to me that SSEG has type PROGBITS.
* The hexfile also states it starts at 0x8000:
:04 8000 00 82008007 73 // 04 bytes at 8000 type 00 being 82008007 checksum 73
Objcopy moved the elf contents to 0x7FFF.
Objcopy also ignored the non-filled-in places below 0x8000, but that is probably because you gave it no --gap-fill value.