1

According to this tutorial: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html, I can embed so piece of code inside a elf header structure.

One step before, where my code and elf header were separate (also in the tutorial), it works. But after that, it does not.

This is my source:

BITS 32
    org 0x08048000
ehdr:
    db 0x7F, "ELF"
    db 1,1,1,0 ;e_indent = magic numbers, 32objects, 2compl, arch
    ;times 8 db 0 ; to the end of e_indent buffer (e_indent[16])
    ;PROGRAM EMBEDDED IN ELF HEADER
_start:
    mov bl, 42
    xor eax, eax
    inc eax
    int 0x80
    dw 2; e_type (2 == executable type)
    dw 3; e_machine (3 == intel_80386)
    dd 1; e_version (1 == current_version)
    dd _start; e_entry
    dd phdr - $$; e_phoff (size between this struct and struct phdr)
    dd 0; e_shoff -----> why is offset 0? == org ?
    dd 0; e_flags (should some processor specific flags, do not know value 0)
    dw ehdr_size; e_ehsize
    dw phdr_size; e_phentsize
    dw 1; e_phnum (real number of program headers, do not know what it means)
    dw 0; e_shentsize (because e_shoff == 0)
    dw 0; e_shnum
    dw 0; e_shstrndx

ehdr_size equ $ - ehdr

phdr:
    dd 1; p_type (1 == loadable program segment)
    dd 0; p_offset (segment file offset, but why 0, beginning?)
    dd $$; p_vaddr (segment virtual address, $$ == org)
    dd $$; p_paddr (segment physical address, $$ == org)
    dd file_size; p_filesz (segment size in file)
    dd file_size; p_memsz (segment size in memory)
    dd 5; p_flags (((1<<0) | (1<<2))) == segment is readable and executable)
    dd 0x1000; p_align (segment alignment - 4096 page alignment)

phdr_size equ $ - phdr
file_size equ $ - $$

There are just my comments after viewing the meanings of members of the struct in elf.h file.

Compiled as:

nasm -fbin -o a.out a.s
chmod +x a.out
./a.out
bash: ./a.out: cannot execute binary file: Exec format error

As I said, before, it was separated, but work. After "merging", it stops working. Some ideas why?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
autistic456
  • 183
  • 1
  • 10

1 Answers1

1

You're not embedding source code (ASCII text), you're trying to embed machine code instructions into the ELF header.

Yours assembles to 83 bytes, but the article has an 84 byte version. It seems you changed something vs. the article's version, breaking it. Compare the binaries or source to figure out what you broke that makes the ELF headers invalid.

 (after assembling both your source and the working source from the article)
$ file tiny-84
tiny-84: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, no section header
$ file tiny-bad
tiny-bad: ELF 32-bit LSB *unknown arch 0x100* (SYSV)
$ cmp tiny-84 tiny-bad
tiny-84 tiny-bad differ: byte 9, line 1

Turns out the difference is on the 2nd data line of the ehdr:

both versions        db      0x7F, "ELF"                     ;   e_ident
-theirs              db      1, 1, 1, 0, 0
+yours               db      1, 1, 1, 0    ;e_indent = magic numbers, 32objects, 2compl, arch

(diff formatting hand tweaked to line them up)

So you left out one byte, misaligning all later bytes relative to their intended position in the ELF header. Obviously this breaks it, but fortunately having a known-good example to binary-compare against made it easy to find the problem.


In practice I used cmp -l tiny-84 tiny-bad to print the mismatching bytes of the binary. When it spewed a lot of differences, that plus the file size mismatch was strong evidence of a missing bytes skewing everything, rather than just 1 field having the wrong value. Also you can visually see the skew:

$ cmp -l tiny-84 tiny-bad
 9   0 263
10 263  52
11  52  61
12  61 300
13 300 100
14 100 315
15 315 200
16 200   2
17   2   0
...
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • I have some question regarding the start address of it. As seen above, it starts at `org`, so I can assume that `$$ == org` as `$$` is start of section, which starts at that address. However, a memeber of the header struct `e_shoff` -> offset of section header table has `0`. What is meas? It means that the section header table is not even presence the the elf, and therefor its size `e_shentsize` is also `0`. – autistic456 Jun 09 '20 at 09:05
  • And just offtopic question: How could I implement the `$$` - startOfSection address in gas? – autistic456 Jun 09 '20 at 09:06
  • @autistic456: You can use `nasm tiny.asm -l /dev/stdout | less` to output a listing to stdout, where you can see the hex value of `$$`. It's like a hexdump mixed with source, so you can see how `$$` expands. It's actually `0` in this case; I'm not sure when it would ever be non-zero. [What's the real meaning of $$ in nasm](https://stackoverflow.com/q/14928741) has some info. But it's useful for `$ - $$` to make sure it's a length and the assembler doesn't try to fill in a full absolute address, maybe? – Peter Cordes Jun 09 '20 at 09:07
  • why is it `0`? What about the `org == 0x08048000`? start of the program address? The `$$` should not be `0` – autistic456 Jun 09 '20 at 09:12
  • @autistic456: I don't know. Maybe if you had a 16-bit segment that didn't start at offset=0 it would be relevant. (i.e. a section or "segment" that wasn't paragraph-aligned). IDK how to do the equivalent in GAS. Probably just put a label at the start of the section and do `. - start_label`. – Peter Cordes Jun 09 '20 at 09:14