Skip to content

Commit 3bd86da

Browse files
authored
Merge pull request #272 from sysprog21/improve-elf
Establish read-only memory sections and implement C const qualifier
2 parents c38ee81 + 38cee09 commit 3bd86da

18 files changed

+407
-82
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ int fib(int n) def int @fib(int %n)
237237
238238
## Known Issues
239239
240-
1. The generated ELF lacks .bss and .rodata sections
241240
2. Full `<stdarg.h>` support is not available. Variadic functions work via direct pointer arithmetic.
242241
See the `printf` implementation in `lib/c.c` for the supported approach.
243242
3. The C front-end operates directly on token streams without building a full AST.

src/arm-codegen.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
9898
elf_offset += 116;
9999
return;
100100
case OP_load_data_address:
101+
case OP_load_rodata_address:
101102
elf_offset += 8;
102103
return;
103104
case OP_address_of_func:
@@ -188,9 +189,9 @@ void emit(int code)
188189
void emit_ph2_ir(ph2_ir_t *ph2_ir)
189190
{
190191
func_t *func;
191-
int rd = ph2_ir->dest;
192-
int rn = ph2_ir->src0;
193-
int rm = ph2_ir->src1;
192+
const int rd = ph2_ir->dest;
193+
const int rn = ph2_ir->src0;
194+
int rm = ph2_ir->src1; /* Not const because OP_trunc modifies it */
194195
int ofs;
195196

196197
/* Prepare this variable to reuse code for:
@@ -288,6 +289,10 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
288289
emit(__movw(__AL, rd, ph2_ir->src0 + elf_data_start));
289290
emit(__movt(__AL, rd, ph2_ir->src0 + elf_data_start));
290291
return;
292+
case OP_load_rodata_address:
293+
emit(__movw(__AL, rd, ph2_ir->src0 + elf_rodata_start));
294+
emit(__movt(__AL, rd, ph2_ir->src0 + elf_rodata_start));
295+
return;
291296
case OP_address_of_func:
292297
func = find_func(ph2_ir->func_name);
293298
ofs = elf_code_start + func->bbs->elf_offset;
@@ -310,7 +315,7 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
310315
emit(__movt(__AL, __r8, ph2_ir->src1 + 4));
311316
emit(__add_r(__AL, __sp, __sp, __r8));
312317
emit(__lw(__AL, __lr, __sp, -4));
313-
emit(__blx(__AL, __lr));
318+
emit(__bx(__AL, __lr));
314319
return;
315320
case OP_add:
316321
emit(__add_r(__AL, rd, rn, rm));
@@ -450,6 +455,8 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
450455
void code_generate(void)
451456
{
452457
elf_data_start = elf_code_start + elf_offset;
458+
elf_rodata_start = elf_data_start + elf_data->size;
459+
elf_bss_start = elf_rodata_start + elf_rodata->size;
453460

454461
/* start */
455462
emit(__movw(__AL, __r8, GLOBAL_FUNC->stack_size));
@@ -477,7 +484,7 @@ void code_generate(void)
477484
emit(__mov_r(__AL, __r4, __r5));
478485
emit(__mov_r(__AL, __r5, __r6));
479486
emit(__svc());
480-
emit(__mov_r(__AL, __pc, __lr));
487+
emit(__bx(__AL, __lr));
481488

482489
ph2_ir_t *ph2_ir;
483490
for (ph2_ir = GLOBAL_FUNC->bbs->ph2_ir_list.head; ph2_ir;

src/arm.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -324,17 +324,17 @@ int __bl(arm_cond_t cond, int ofs)
324324
return arm_encode(cond, 176, 0, 0, 0) + (o & 16777215);
325325
}
326326

327-
int __blx(arm_cond_t cond, arm_reg rd)
328-
{
329-
return arm_encode(cond, 18, 15, 15, rd + 3888);
330-
}
331-
332327
int __bx(arm_cond_t cond, arm_reg rm)
333328
{
334329
/* BX: Branch and Exchange */
335330
return (cond << 28) | 0x012FFF10 | rm;
336331
}
337332

333+
int __blx(arm_cond_t cond, arm_reg rd)
334+
{
335+
return arm_encode(cond, 18, 15, 15, rd + 3888);
336+
}
337+
338338
int __mul(arm_cond_t cond, arm_reg rd, arm_reg r1, arm_reg r2)
339339
{
340340
return arm_encode(cond, 0, rd, 0, (r1 << 8) + 144 + r2);

src/defs.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ typedef enum {
179179
T_break,
180180
T_default,
181181
T_continue,
182+
T_const, /* const qualifier */
182183
/* C pre-processor directives */
183184
T_cppd_include,
184185
T_cppd_define,
@@ -260,8 +261,9 @@ typedef enum {
260261

261262
OP_allocat, /* allocate space on stack */
262263
OP_assign,
263-
OP_load_constant, /* load constant */
264-
OP_load_data_address, /* lookup address of a constant in data section */
264+
OP_load_constant, /* load constant */
265+
OP_load_data_address, /* lookup address of a constant in data section */
266+
OP_load_rodata_address, /* lookup address of a constant in rodata section */
265267

266268
/* control flow */
267269
OP_branch, /* conditional jump */
@@ -353,7 +355,8 @@ struct var {
353355
int ptr_level;
354356
bool is_func;
355357
bool is_global;
356-
bool address_taken; /* true if variable address was taken (&var) */
358+
bool is_const_qualified; /* true if variable has const qualifier */
359+
bool address_taken; /* true if variable address was taken (&var) */
357360
int array_size;
358361
int array_dim1, array_dim2; /* first/second dimension size for 2D arrays */
359362
int offset; /* offset from stack or frame, index 0 is reserved */

src/elf.c

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
int elf_symbol_index;
1515

16-
void elf_write_str(strbuf_t *elf_array, char *vals)
16+
void elf_write_str(strbuf_t *elf_array, const char *vals)
1717
{
1818
/*
1919
* Note that strbuf_puts() does not push the null character.
@@ -64,8 +64,7 @@ void elf_generate_header(void)
6464
}
6565

6666
elf32_hdr_t hdr;
67-
/*
68-
* The following table explains the meaning of each field in the
67+
/* The following table explains the meaning of each field in the
6968
* ELF32 file header.
7069
*
7170
* Notice that the following values are hexadecimal.
@@ -134,26 +133,34 @@ void elf_generate_header(void)
134133
hdr.e_version = 1; /* ELF version */
135134
hdr.e_entry = ELF_START + elf_header_len; /* entry point */
136135
hdr.e_phoff = 0x34; /* program header offset */
137-
hdr.e_shoff = elf_header_len + elf_code->size + elf_data->size + 39 +
138-
elf_symtab->size +
139-
elf_strtab->size; /* section header offset */
140-
hdr.e_flags = ELF_FLAGS; /* flags */
141-
hdr.e_ehsize[0] = (char) 0x34; /* header size */
136+
/* Section header offset: The section headers come after symtab, strtab, and
137+
* shstrtab which are all written as part of elf_section buffer.
138+
* shstrtab size = 1 (null) + 10 (.shstrtab\0) + 6 (.text\0) + 6 (.data\0) +
139+
* 8 (.rodata\0) + 5 (.bss\0) + 8 (.symtab\0) + 8
140+
* (.strtab\0) + 1 (padding) = 53
141+
*/
142+
const int shstrtab_size = 53; /* section header string table with padding */
143+
hdr.e_shoff = elf_header_len + elf_code->size + elf_data->size +
144+
elf_rodata->size + elf_symtab->size + elf_strtab->size +
145+
shstrtab_size;
146+
hdr.e_flags = ELF_FLAGS; /* flags */
147+
hdr.e_ehsize[0] = (char) 0x34; /* header size */
142148
hdr.e_ehsize[1] = 0;
143149
hdr.e_phentsize[0] = (char) 0x20; /* program header size */
144150
hdr.e_phentsize[1] = 0;
145151
hdr.e_phnum[0] = 1; /* number of program headers */
146152
hdr.e_phnum[1] = 0;
147153
hdr.e_shentsize[0] = (char) 0x28; /* section header size */
148154
hdr.e_shentsize[1] = 0;
149-
hdr.e_shnum[0] = 6; /* number of section headers */
155+
/* number of section headers: .rodata and .bss included */
156+
hdr.e_shnum[0] = 8;
150157
hdr.e_shnum[1] = 0;
151-
hdr.e_shstrndx[0] = 5; /* section index with names */
158+
/* section index with names: updated for new sections */
159+
hdr.e_shstrndx[0] = 7;
152160
hdr.e_shstrndx[1] = 0;
153161
elf_write_blk(elf_header, &hdr, sizeof(elf32_hdr_t));
154162

155-
/*
156-
* Explain the meaning of each field in the ELF32 program header.
163+
/* Explain the meaning of each field in the ELF32 program header.
157164
*
158165
* | Program | |
159166
* & | Header bytes | Explanation |
@@ -176,14 +183,16 @@ void elf_generate_header(void)
176183
*/
177184
/* program header - code and data combined */
178185
elf32_phdr_t phdr;
179-
phdr.p_type = 1; /* PT_LOAD */
180-
phdr.p_offset = elf_header_len; /* offset of segment */
181-
phdr.p_vaddr = ELF_START + elf_header_len; /* virtual address */
182-
phdr.p_paddr = ELF_START + elf_header_len; /* physical address */
183-
phdr.p_filesz = elf_code->size + elf_data->size; /* size in file */
184-
phdr.p_memsz = elf_code->size + elf_data->size; /* size in memory */
185-
phdr.p_flags = 7; /* flags */
186-
phdr.p_align = 4; /* alignment */
186+
phdr.p_type = 1; /* PT_LOAD */
187+
phdr.p_offset = elf_header_len; /* offset of segment */
188+
phdr.p_vaddr = ELF_START + elf_header_len; /* virtual address */
189+
phdr.p_paddr = ELF_START + elf_header_len; /* physical address */
190+
phdr.p_filesz = elf_code->size + elf_data->size +
191+
elf_rodata->size; /* size in file - includes .rodata */
192+
phdr.p_memsz = elf_code->size + elf_data->size + elf_rodata->size +
193+
elf_bss_size; /* size in memory - includes .bss */
194+
phdr.p_flags = 7; /* flags */
195+
phdr.p_align = 4; /* alignment */
187196
elf_write_blk(elf_header, &phdr, sizeof(elf32_phdr_t));
188197
}
189198

@@ -195,26 +204,39 @@ void elf_generate_sections(void)
195204
return;
196205
}
197206

207+
int section_data_size = 0;
208+
int shstrtab_start = 0; /* Track start of shstrtab */
209+
198210
/* symtab section */
199211
for (int b = 0; b < elf_symtab->size; b++)
200212
elf_write_byte(elf_section, elf_symtab->elements[b]);
213+
section_data_size += elf_symtab->size;
201214

202215
/* strtab section */
203216
for (int b = 0; b < elf_strtab->size; b++)
204217
elf_write_byte(elf_section, elf_strtab->elements[b]);
218+
section_data_size += elf_strtab->size;
205219

206-
/* shstr section; len = 39 */
220+
/* shstr section - compute size dynamically */
221+
shstrtab_start = elf_section->size;
207222
elf_write_byte(elf_section, 0);
208223
elf_write_str(elf_section, ".shstrtab");
209224
elf_write_byte(elf_section, 0);
210225
elf_write_str(elf_section, ".text");
211226
elf_write_byte(elf_section, 0);
212227
elf_write_str(elf_section, ".data");
213228
elf_write_byte(elf_section, 0);
229+
elf_write_str(elf_section, ".rodata");
230+
elf_write_byte(elf_section, 0);
231+
elf_write_str(elf_section, ".bss");
232+
elf_write_byte(elf_section, 0);
214233
elf_write_str(elf_section, ".symtab");
215234
elf_write_byte(elf_section, 0);
216235
elf_write_str(elf_section, ".strtab");
217236
elf_write_byte(elf_section, 0);
237+
/* Add padding byte for alignment - some tools expect this */
238+
elf_write_byte(elf_section, 0);
239+
int shstrtab_size = elf_section->size - shstrtab_start;
218240

219241
/* section header table */
220242
elf32_shdr_t shdr;
@@ -288,22 +310,51 @@ void elf_generate_sections(void)
288310
elf_write_blk(elf_section, &shdr, sizeof(elf32_shdr_t));
289311
ofs += elf_data->size;
290312

313+
/* .rodata */
314+
shdr.sh_name = 0x17; /* Offset in shstrtab for ".rodata" */
315+
shdr.sh_type = 1; /* SHT_PROGBITS */
316+
shdr.sh_flags = 2; /* SHF_ALLOC only (read-only) */
317+
shdr.sh_addr = elf_code_start + elf_code->size + elf_data->size;
318+
shdr.sh_offset = ofs;
319+
shdr.sh_size = elf_rodata->size;
320+
shdr.sh_link = 0;
321+
shdr.sh_info = 0;
322+
shdr.sh_addralign = 4;
323+
shdr.sh_entsize = 0;
324+
elf_write_blk(elf_section, &shdr, sizeof(elf32_shdr_t));
325+
ofs += elf_rodata->size;
326+
327+
/* .bss */
328+
shdr.sh_name = 0x1f; /* Offset in shstrtab for ".bss" */
329+
shdr.sh_type = 8; /* SHT_NOBITS */
330+
shdr.sh_flags = 3; /* SHF_ALLOC | SHF_WRITE */
331+
shdr.sh_addr =
332+
elf_code_start + elf_code->size + elf_data->size + elf_rodata->size;
333+
shdr.sh_offset = ofs; /* File offset (not actually used for NOBITS) */
334+
shdr.sh_size = elf_bss_size;
335+
shdr.sh_link = 0;
336+
shdr.sh_info = 0;
337+
shdr.sh_addralign = 4;
338+
shdr.sh_entsize = 0;
339+
elf_write_blk(elf_section, &shdr, sizeof(elf32_shdr_t));
340+
/* Note: .bss is not written to file (SHT_NOBITS) */
341+
291342
/* .symtab */
292-
shdr.sh_name = 0x17;
343+
shdr.sh_name = 0x24; /* Updated offset for ".symtab" */
293344
shdr.sh_type = 2;
294345
shdr.sh_flags = 0;
295346
shdr.sh_addr = 0;
296347
shdr.sh_offset = ofs;
297348
shdr.sh_size = elf_symtab->size;
298-
shdr.sh_link = 4;
349+
shdr.sh_link = 6; /* Link to .strtab (section 6) */
299350
shdr.sh_info = elf_symbol_index;
300351
shdr.sh_addralign = 4;
301352
shdr.sh_entsize = 16;
302353
elf_write_blk(elf_section, &shdr, sizeof(elf32_shdr_t));
303354
ofs += elf_symtab->size;
304355

305356
/* .strtab */
306-
shdr.sh_name = 0x1f;
357+
shdr.sh_name = 0x2c; /* Updated offset for ".strtab" */
307358
shdr.sh_type = 3;
308359
shdr.sh_flags = 0;
309360
shdr.sh_addr = 0;
@@ -322,7 +373,7 @@ void elf_generate_sections(void)
322373
shdr.sh_flags = 0;
323374
shdr.sh_addr = 0;
324375
shdr.sh_offset = ofs;
325-
shdr.sh_size = 39;
376+
shdr.sh_size = shstrtab_size; /* Computed dynamically */
326377
shdr.sh_link = 0;
327378
shdr.sh_info = 0;
328379
shdr.sh_addralign = 1;
@@ -333,22 +384,25 @@ void elf_generate_sections(void)
333384
void elf_align(void)
334385
{
335386
/* Check for null pointers to prevent crashes */
336-
if (!elf_data || !elf_symtab || !elf_strtab) {
387+
if (!elf_data || !elf_rodata || !elf_symtab || !elf_strtab) {
337388
error("ELF buffers not initialized for alignment");
338389
return;
339390
}
340391

341392
while (elf_data->size & 3)
342393
elf_write_byte(elf_data, 0);
343394

395+
while (elf_rodata->size & 3)
396+
elf_write_byte(elf_rodata, 0);
397+
344398
while (elf_symtab->size & 3)
345399
elf_write_byte(elf_symtab, 0);
346400

347401
while (elf_strtab->size & 3)
348402
elf_write_byte(elf_strtab, 0);
349403
}
350404

351-
void elf_add_symbol(char *symbol, int pc)
405+
void elf_add_symbol(const char *symbol, int pc)
352406
{
353407
/* Check for null pointers to prevent crashes */
354408
if (!symbol || !elf_symtab || !elf_strtab) {
@@ -366,7 +420,7 @@ void elf_add_symbol(char *symbol, int pc)
366420
elf_symbol_index++;
367421
}
368422

369-
void elf_generate(char *outfile)
423+
void elf_generate(const char *outfile)
370424
{
371425
elf_align();
372426
elf_generate_header();
@@ -387,6 +441,9 @@ void elf_generate(char *outfile)
387441
fputc(elf_code->elements[i], fp);
388442
for (int i = 0; i < elf_data->size; i++)
389443
fputc(elf_data->elements[i], fp);
444+
for (int i = 0; i < elf_rodata->size; i++)
445+
fputc(elf_rodata->elements[i], fp);
446+
/* Note: .bss is not written to file (SHT_NOBITS) */
390447
for (int i = 0; i < elf_section->size; i++)
391448
fputc(elf_section->elements[i], fp);
392449
fclose(fp);

0 commit comments

Comments
 (0)