int symbols_set(struct _symbols *symbols, char *name, int address) { struct _symbols_data *symbols_data = NULL; symbols_data = symbols_find(symbols, name); if (symbols_data == NULL) { if (symbols_append(symbols, name, address) != 0) { return -1; } symbols_data = symbols_find(symbols, name); symbols_data->flag_rw = 1; } else if (symbols_data->flag_rw == 1) { symbols_data->address = address; } else { return -1; } return 0; }
/** * Load text symbols from the file into supplied table. * * @param bc the BFD context pointing to the file * @param st the symbol table where symbols should be added */ static void bfd_util_load_text(bfd_ctx_t *bc, symbols_t *st) { long i; asymbol* empty; void *p; bfd_ctx_check(bc); g_assert(st != NULL); if (0 == bc->count) return; mutex_lock_fast(&bc->lock); g_assert(bc->symbols != NULL); empty = bfd_make_empty_symbol(bc->handle); symbols_lock(st); for ( i = 0, p = bc->symbols; i < bc->count; i++, p = ptr_add_offset(p, bc->symsize) ) { asymbol *sym; symbol_info syminfo; sym = bfd_minisymbol_to_symbol(bc->handle, bc->dynamic, p, empty); bfd_get_symbol_info(bc->handle, sym, &syminfo); if ('T' == syminfo.type || 't' == syminfo.type) { const char *name = bfd_asymbol_name(sym); if (name != NULL && name[0] != '.') { void *addr = ulong_to_pointer(syminfo.value); symbols_append(st, addr, name); } } } symbols_unlock(st); mutex_unlock_fast(&bc->lock); }
int assemble(struct _asm_context *asm_context) { char token[TOKENLEN]; int token_type; while(1) { token_type = tokens_get(asm_context, token, TOKENLEN); #ifdef DEBUG printf("%d: <%d> %s\n", asm_context->line, token_type, token); #endif if (token_type == TOKEN_EOF) break; if (token_type == TOKEN_EOL) { if (asm_context->macros.stack_ptr == 0) { asm_context->line++; } } else if (token_type == TOKEN_LABEL) { int param_count_temp; if (macros_lookup(&asm_context->macros, token, ¶m_count_temp) != NULL) { print_already_defined(asm_context, token); return -1; } if (symbols_append(&asm_context->symbols, token, asm_context->address / asm_context->bytes_per_address) == -1) { return -1; } } else if (token_type == TOKEN_POUND || IS_TOKEN(token,'.')) { token_type = tokens_get(asm_context, token, TOKENLEN); #ifdef DEBUG printf("%d: <%d> %s\n", asm_context->line, token_type, token); #endif if (token_type == TOKEN_EOF) break; if (strcasecmp(token, "define") == 0) { if (macros_parse(asm_context, IS_DEFINE) != 0) return -1; } else if (strcasecmp(token, "ifdef") == 0) { parse_ifdef(asm_context, 0); } else if (strcasecmp(token, "ifndef") == 0) { parse_ifdef(asm_context, 1); } else if (strcasecmp(token, "if") == 0) { parse_if(asm_context); } else if (strcasecmp(token, "endif") == 0) { if (asm_context->ifdef_count < 1) { printf("Error: unmatched .endif at %s:%d\n", asm_context->filename, asm_context->ifdef_count); return -1; } return 0; } else if (strcasecmp(token, "else") == 0) { if (asm_context->ifdef_count < 1) { printf("Error: unmatched .else at %s:%d\n", asm_context->filename, asm_context->ifdef_count); return -1; } return 2; } else if (strcasecmp(token, "include") == 0) { if (parse_include(asm_context) != 0) return -1; } else if (strcasecmp(token, "binfile") == 0) { if (parse_binfile(asm_context) != 0) return -1; } else if (strcasecmp(token, "code") == 0) { asm_context->segment = SEGMENT_CODE; } else if (strcasecmp(token, "bss") == 0) { asm_context->segment = SEGMENT_BSS; } else if (strcasecmp(token, "msp430_cpu4") == 0) { asm_context->msp430_cpu4 = 1; } else if (strcasecmp(token, "macro") == 0) { if (macros_parse(asm_context, IS_MACRO) != 0) return -1; } else if (strcasecmp(token, "pragma") == 0) { if (parse_pragma(asm_context) != 0) return -1; } else if (strcasecmp(token, "device") == 0) { if (parse_device(asm_context) != 0) return -1; } else if (strcasecmp(token, "set") == 0) { if (parse_set(asm_context) != 0) return -1; } else if (strcasecmp(token, "export") == 0) { if (parse_export(asm_context) != 0) return -1; } else if (strcasecmp(token, "equ") == 0 || strcasecmp(token, "def")==0) { if (parse_equ(asm_context) != 0) return -1; } else { int ret = check_for_directive(asm_context, token); if (ret == 2) break; if (ret == -1) return -1; if (ret != 1) { printf("Error: Unknown directive '%s' at %s:%d.\n", token, asm_context->filename, asm_context->line); return -1; } } } else if (token_type == TOKEN_STRING) { int ret = check_for_directive(asm_context, token); if (ret == 2) break; if (ret == -1) return -1; if (ret != 1) { int start_address = asm_context->address; char token2[TOKENLEN]; int token_type2; token_type2 = tokens_get(asm_context, token2, TOKENLEN); if (strcasecmp(token2, "equ") == 0) { //token_type2 = tokens_get(asm_context, token2, TOKENLEN); int ptr = 0; int ch = '\n'; while(1) { ch = tokens_get_char(asm_context); if (ch == EOF || ch == '\n') break; if (ch == '*' && ptr > 0 && token2[ptr-1] == '/') { macros_strip_comment(asm_context); ptr--; continue; } token2[ptr++] = ch; if (ptr == TOKENLEN-1) { printf("Internal Error: token overflow at %s:%d.\n", __FILE__, __LINE__); return -1; } } token2[ptr] = 0; tokens_unget_char(asm_context, ch); macros_strip(token2); macros_append(asm_context, token, token2, 0); } else { tokens_push(asm_context, token2, token_type2); ret = asm_context->parse_instruction(asm_context, token); if (asm_context->pass == 2 && asm_context->list != NULL && asm_context->include_count == 0) { asm_context->list_output(asm_context, start_address); fprintf(asm_context->list, "\n"); } if (ret < 0) return -1; if (asm_context->macros.stack_ptr == 0) { asm_context->line++; } asm_context->instruction_count++; if (asm_context->address > start_address) { asm_context->code_count += (asm_context->address - start_address); } } } } else { print_error_unexp(token, asm_context); return -1; } } if (asm_context->error == 1) { return -1; } return 0; }
int read_elf(char *filename, struct _memory *memory, uint8_t *cpu_type, struct _symbols *symbols) { FILE *in; uint8_t e_ident[16]; int e_shoff; int e_shentsize; int e_shnum; int e_shstrndx; int n; int start, end; struct _elf32_shdr elf32_shdr; long strtab_offset = 0; get_int16_t get_int16; get_int32_t get_int32; memory_clear(memory); //memset(dirty, 0, memory->size); start = -1; end = -1; in = fopen(filename, "rb"); if (in == 0) { return -1; } memset(e_ident, 0, 16); n = fread(e_ident, 1, 16, in); if (e_ident[0] != 0x7f || e_ident[1] != 'E' || e_ident[2] != 'L' || e_ident[3] != 'F') { //printf("Not an ELF file.\n"); fclose(in); return -2; } #define EI_CLASS 4 // 1=32 bit, 2=64 bit #define EI_DATA 5 // 1=little endian, 2=big endian #define EI_OSABI 7 // 0=SysV, 255=Embedded if (e_ident[EI_CLASS] != 1) // let's let other stuff in || e_ident[7]!=0xff) { printf("ELF Error: e_ident shows incorrect type\n"); fclose(in); return -1; } // EI_DATA if (e_ident[EI_DATA] == 1) { memory->endian = ENDIAN_LITTLE; get_int16 = get_int16_le; get_int32 = get_int32_le; } else if (e_ident[EI_DATA] == 2) { memory->endian = ENDIAN_BIG; get_int16 = get_int16_be; get_int32 = get_int32_be; } else { printf("ELF Error: EI_DATA incorrect data encoding\n"); fclose(in); return -1; } get_int16(in); n = get_int16(in); switch(n) { case 8: case 10: *cpu_type = CPU_TYPE_MIPS; break; case 40: *cpu_type = CPU_TYPE_ARM; break; case 83: *cpu_type = CPU_TYPE_AVR8; break; case 105: *cpu_type = CPU_TYPE_MSP430; break; case 118: *cpu_type = CPU_TYPE_DSPIC; break; default: printf("ELF Error: e_machine unknown\n"); fclose(in); return -1; } fseek(in, 32, SEEK_SET); e_shoff = get_int32(in); fseek(in, 46, SEEK_SET); e_shentsize = get_int16(in); e_shnum = get_int16(in); e_shstrndx = get_int16(in); //printf("e_shoff=%d\n", e_shoff); //printf("e_shentsize=%d\n", e_shentsize); //printf("e_shnum=%d\n", e_shnum); //printf("e_shstrndx=%d\n", e_shstrndx); fseek(in, e_shoff + (e_shstrndx * e_shentsize) + 16, SEEK_SET); int stroffset = get_int32(in); char name[32]; // Need to find .strtab so we can fill in symbol names for (n = 0; n < e_shnum; n++) { fseek(in, e_shoff + (n * e_shentsize), SEEK_SET); read_shdr(in, &elf32_shdr, get_int32); if (elf32_shdr.sh_type == SHT_STRTAB) { read_name(in, name, 32, stroffset + elf32_shdr.sh_name); if (strcmp(name, ".strtab") == 0) { strtab_offset = elf32_shdr.sh_offset; break; } } } for (n = 0; n < e_shnum; n++) { // FIXME - a little inefficient eh? fseek(in, e_shoff + (n * e_shentsize), SEEK_SET); read_shdr(in, &elf32_shdr, get_int32); read_name(in, name, 32, stroffset + elf32_shdr.sh_name); //printf("name=%s\n", name); //int is_text = strncmp(name, ".text", 5) == 0 ? 1 : 0; int is_text = (elf32_shdr.sh_flags & SHF_EXECINSTR) != 0 ? 1 : 0; if (is_text || strncmp(name, ".data", 5) == 0 || strcmp(name, ".vectors") == 0) { if (is_text) { if (start == -1) { start = elf32_shdr.sh_addr; } else if (start > elf32_shdr.sh_addr) { start = elf32_shdr.sh_addr; } if (end == -1) { end = elf32_shdr.sh_addr + elf32_shdr.sh_size - 1; } else if (end < elf32_shdr.sh_addr + elf32_shdr.sh_size) { end = elf32_shdr.sh_addr+elf32_shdr.sh_size - 1; } } long marker = ftell(in); fseek(in, elf32_shdr.sh_offset, SEEK_SET); int n; for (n = 0; n < elf32_shdr.sh_size; n++) { if (elf32_shdr.sh_addr + n >= memory->size) break; memory_write_m(memory, elf32_shdr.sh_addr + n, getc(in)); } fseek(in, marker, SEEK_SET); printf("Loaded %d %s bytes from 0x%04x\n", n, name, elf32_shdr.sh_addr); } else if (elf32_shdr.sh_type == SHT_SYMTAB && symbols != NULL) { long marker = ftell(in); fseek(in, elf32_shdr.sh_offset, SEEK_SET); for (n = 0; n < elf32_shdr.sh_size; n += 16) { char name[128]; struct _elf32_sym elf32_sym; elf32_sym.st_name = get_int32(in); elf32_sym.st_value = get_int32(in); elf32_sym.st_size = get_int32(in); elf32_sym.st_info = getc(in); elf32_sym.st_other = getc(in); elf32_sym.st_shndx = get_int16(in); read_name(in, name, 128, strtab_offset + elf32_sym.st_name); printf("symbol %12s 0x%04x\n", name, elf32_sym.st_value); if (elf32_sym.st_info != STT_NOTYPE && elf32_sym.st_info != STT_SECTION && elf32_sym.st_info != STT_FILE) { symbols_append(symbols, name, elf32_sym.st_value); } } fseek(in, marker, SEEK_SET); } } memory->low_address = start; memory->high_address = end; fclose(in); return start; }