File: elf_creator.c

package info (click to toggle)
python-pyelftools 0.29-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 64,480 kB
  • sloc: python: 14,475; ansic: 184; asm: 86; makefile: 22; cpp: 18
file content (204 lines) | stat: -rw-r--r-- 7,476 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* Loosely based on the code in a Knol by Roberto Garcia Lopez:
** 
** http://knol.google.com/k/roberto-garca-lpez/creating-elf-relocatable-object-files/1ohwel4gqkcn2/3#
**
** Note: This file is released under the terms of the LGPL2 license.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <libelf.h>
#include <err.h>
#include <sysexits.h>


const char* OUTFILE = "generated.o";

// Definition of the default string table section ".shstrtab"
const char defaultStrTable[] = 
{
    /* offset 00 */ '\0',  // The NULL section
    /* offset 01 */ '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0',
    /* offset 11 */ '.', 's', 't', 'r', 't', 'a', 'b', '\0',
    /* offset 19 */ '.', 's', 'y', 'm', 't', 'a', 'b', '\0',
    /* offset 27 */ '.', 'c', 'o', 'm', 'm', 'e', 'n', 't', '\0',
    /* offset 36 */ '.', 'b', 's', 's', '\0',
    /* offset 41 */ '.', 'd', 'a', 't', 'a', '\0',
    /* offset 47 */ '.', 'r', 'e', 'l', '.', 't', 'e', 'x', 't', '\0',
    /* offset 57 */ '.', 't', 'e', 'x', 't', '\0'
};

const char defaultStrTableLen = sizeof(defaultStrTable);

// Offsets of section names in the string table
const char _shstrtab_offset = 1;
const char _strtab_offset = 11;
const char _symtab_offset = 19;
const char _text_offset = 57;

// Position of sections within the object file
const char _shstrtab = 1;
const char _strtab = 2;
const char _symtab = 3;
const char _text = 4;

const char TEXT_CONTENTS[] = {0x91, 0x92, 0x93, 0x94};


//----------------------------------------------------------------------------

int main()
{
    int FileDes;
    Elf *pElf;
    Elf32_Ehdr *pEhdr;
    Elf32_Shdr *pShdr;
    Elf_Scn *pScn;
    Elf_Data *pData;

    // Create the ELF header
    if (elf_version(EV_CURRENT) == EV_NONE) // It must appear before "elf_begin()"
        errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1));

    if ((FileDes = open(OUTFILE, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0)
        errx(EX_OSERR, "open \"%s\" failed", "compiled.o");

    if ((pElf = elf_begin(FileDes, ELF_C_WRITE, NULL)) == NULL)  // 3rd argument is ignored for "ELF_C_WRITE"
        errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));

    if ((pEhdr = elf32_newehdr(pElf)) == NULL)
        errx(EX_SOFTWARE, "elf32_newehdr() failed: %s", elf_errmsg(-1));

    pEhdr->e_ident[EI_CLASS] = ELFCLASS32;  // Defined by Intel architecture
    pEhdr->e_ident[EI_DATA] = ELFDATA2LSB;  // Defined by Intel architecture
    pEhdr->e_machine = EM_386;  // Intel architecture
    pEhdr->e_type = ET_REL;   // Relocatable file (object file)
    pEhdr->e_shstrndx = _shstrtab;    // Point to the shstrtab section

    // Create the section "default section header string table (.shstrtab)"
    if ((pScn = elf_newscn(pElf)) == NULL)
        errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
    if ((pData = elf_newdata(pScn)) == NULL)
        errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));

    pData->d_align = 1;
    pData->d_buf = (void *) defaultStrTable;
    pData->d_type = ELF_T_BYTE;
    pData->d_size = defaultStrTableLen;

    if ((pShdr = elf32_getshdr(pScn)) == NULL)
        errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1));

    pShdr->sh_name = _shstrtab_offset;  // Point to the name of the section
    pShdr->sh_type = SHT_STRTAB;
    pShdr->sh_flags = 0;

    // Create the section ".strtab"
    if ((pScn = elf_newscn(pElf)) == NULL)
        errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
    if ((pData = elf_newdata(pScn)) == NULL)
        errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));

    const char strtab[] = {0, 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', '.','x', 0, '_', 's', 't', 'a', 'r', 't', 0};

    pData->d_align = 1;
    pData->d_buf = (void *) strtab;
    pData->d_type = ELF_T_BYTE;
    pData->d_size = sizeof(strtab);

    if ((pShdr = elf32_getshdr(pScn)) == NULL)
        errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1));

    pShdr->sh_name = _strtab_offset;
    pShdr->sh_type = SHT_STRTAB;
    pShdr->sh_flags = 0;

    // Create the section ".symtab"
    if ((pScn = elf_newscn(pElf)) == NULL)
        errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
    if ((pData = elf_newdata(pScn)) == NULL)
        errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));

    Elf32_Sym x[4];

    // Definition of the undefined section (this must be the first item by the definition of TIS ELF)
    x[0].st_name = 0;
    x[0].st_value = 0;
    x[0].st_size = 0;
    x[0].st_info = 0;
    x[0].st_other = 0;
    x[0].st_shndx = SHN_UNDEF;

    // Definition of the name of the source file (this must be the second item by the definition in TIS ELF)
    x[1].st_name = 1;
    x[1].st_value = 0;
    x[1].st_size = 0;
    x[1].st_info = ELF32_ST_INFO(STB_LOCAL, STT_FILE); // This is the value that st_info must have (because of TIS ELF)
    x[1].st_other = 0;
    x[1].st_shndx = SHN_ABS;  // The section where the symbol is

    // Definition of the ".text" section as a section in the ".symtab" section
    x[2].st_name = 0;
    x[2].st_value = 0;
    x[2].st_size = 0;
    x[2].st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
    x[2].st_other = 0;
    x[2].st_shndx = _text;  // The section where the symbol is

    // Definition of the "_start" symbol
    x[3].st_name = 13;  // Offset in the "strtab" section where the name start
    x[3].st_value = 0;
    x[3].st_size = 0;
    x[3].st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE);
    x[3].st_other = 0;
    x[3].st_shndx = _text;  // The section where the symbol is

    pData->d_align = 4;
    pData->d_buf = (void *) x;
    pData->d_type = ELF_T_BYTE;
    pData->d_size = sizeof(x);

    if ((pShdr = elf32_getshdr(pScn)) == NULL)
        errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1));

    pShdr->sh_name = _symtab_offset;  // Point to the name of the section
    pShdr->sh_type = SHT_SYMTAB;
    pShdr->sh_flags = 0;
    pShdr->sh_link = _strtab;  // point to the section .strtab (the section that contain the strings)
    pShdr->sh_info = ELF32_ST_INFO(STB_LOCAL, 3);  // the second argument is beause of TIS ELF (One greater than the symbol table index of the last local symbol (binding STB_LOCAL))

    // Create many sections named .text
    for (int i = 0; i < 70000; ++i) {
        if ((pScn = elf_newscn(pElf)) == NULL)
            errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
        if ((pData = elf_newdata(pScn)) == NULL)
            errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));

        pData->d_align = 4;
        pData->d_buf = (void *)TEXT_CONTENTS;
        pData->d_type = ELF_T_BYTE;
        pData->d_size = sizeof(TEXT_CONTENTS);

        if ((pShdr = elf32_getshdr(pScn)) == NULL)
            errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1));

        pShdr->sh_name = _text_offset;
        pShdr->sh_type = SHT_PROGBITS;
        pShdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
    }

    // Update the sections internally
    if (elf_update(pElf, ELF_C_NULL) < 0)
        errx(EX_SOFTWARE, "elf_update(NULL) failed: %s.", elf_errmsg(-1));
    // Write the object file
    if (elf_update(pElf, ELF_C_WRITE) < 0)
        errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1));
    // Close all handles
    elf_end(pElf);
    close(FileDes);
    printf("Generated file: %s\n", OUTFILE);
    
    return 0;
}