#include "../gen.h" #include #include #include #include struct section_default { char *name; int name_len; bool read; bool write; bool execute; int alignment; }; #define SECTION_DEFAULTS_LEN 7 #define MAPPING(name, ...) {name, sizeof(name), __VA_ARGS__} static const struct section_default section_defaults[SECTION_DEFAULTS_LEN] = { MAPPING(".text", true, false, true, 4), MAPPING(".code", true, false, true, 4), MAPPING(".data", true, true, false, 1), MAPPING(".stack", true, true, false, 1), MAPPING(".rodata", true, false, false, 1), MAPPING(".bss", true, true, false, 1), MAPPING(".robss", true, false, false, 1), }; static void section_get_default_perm(struct section *sec, const char *name) { for (int i = 0; i < SECTION_DEFAULTS_LEN; i++) { const struct section_default *defaults = §ion_defaults[i]; if (strncasecmp(name, defaults->name, defaults->name_len)) continue; sec->read = defaults->read; sec->write = defaults->write; sec->execute = defaults->execute; sec->align = defaults->alignment; break; } } int gen_get_section(struct generator *gen, struct section **res, struct string *name) { /// find the section if it exists for (size_t i = 0; i < gen->sections_len; i++) { struct section *sec = &gen->sections[i]; if (sec->name.len != name->len) continue; if (strcmp(sec->name.str, name->str) != 0) continue; *res = sec; return 0; } /// allocate a new one if it doesnt size_t size = gen->sections_size ? gen->sections_size * 2 : 8; void *new = realloc(gen->sections, size * sizeof(struct section)); if (new == NULL) { PERROR("cannot realloc"); return 1; } gen->sections_size = size; gen->sections = new; struct section *sec = &gen->sections[gen->sections_len++]; if (section_init(sec, name)) return 1; *res = sec; return 0; } int section_init(struct section *sec, struct string *name) { sec->len = 0; sec->size = 0; sec->align = 1; sec->data = NULL; sec->read = true; sec->write = true; sec->execute = false; // set defaults section_get_default_perm(sec, name->str); // alloc reftab if (reftab_init(&sec->reftab)) return 1; // copy name if (string_clone(&sec->name, name)) return 1; return 0; } int section_extend(struct section *section, size_t space) { size_t newlen = section->len + space; if (newlen < section->size) return M_SUCCESS; size_t size = section->size ? section->size * 2 + newlen : newlen * 2; void *new = realloc(section->data, size); if (new == NULL) { PERROR("cannot realloc"); return M_ERROR; } section->size = size; section->data = new; return M_SUCCESS; } int section_push(struct section *section, void *data, size_t len) { size_t newlen = section->len + len; size_t zeros = newlen % section->align; if (zeros) zeros = section->align - zeros; if (section_extend(section, len + zeros)) return M_ERROR; memset(section->data + section->len, 0, zeros); memcpy(section->data + section->len + zeros, data, len); section->len += len + zeros; return M_SUCCESS; } int section_zero(struct section *section, size_t len) { size_t zeros = section->len % section->align; if (zeros) zeros = section->align - zeros; if (section_extend(section, len + zeros)) return M_ERROR; memset(section->data + section->len, 0, len + zeros); section->len += len + zeros; return M_SUCCESS; } void section_free(struct section *section) { reftab_free(§ion->reftab); string_free(§ion->name); free(section->data); }