4 Loads a .elf file, extract the code, the data, the eeprom and
5 the "mcu" specification section, also load usable code symbols
6 to be able to print meaningful trace information.
8 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
10 This file is part of simavr.
12 simavr is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
17 simavr is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with simavr. If not, see <http://www.gnu.org/licenses/>.
36 #include "sim_vcd_file.h"
37 #include "avr_eeprom.h"
43 void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
45 if (firmware->frequency)
46 avr->frequency = firmware->frequency;
48 avr->vcc = firmware->vcc;
50 avr->avcc = firmware->avcc;
52 avr->aref = firmware->aref;
53 #if CONFIG_SIMAVR_TRACE
54 avr->trace_data->codeline = firmware->codeline;
57 avr_loadcode(avr, firmware->flash, firmware->flashsize, firmware->flashbase);
58 avr->codeend = firmware->flashsize + firmware->flashbase - firmware->datasize;
59 if (firmware->eeprom && firmware->eesize) {
60 avr_eeprom_desc_t d = { .ee = firmware->eeprom, .offset = 0, .size = firmware->eesize };
61 avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
64 avr_set_command_register(avr, firmware->command_register_addr);
65 avr_set_console_register(avr, firmware->console_register_addr);
67 // rest is initialization of the VCD file
69 if (firmware->tracecount == 0)
71 avr->vcd = malloc(sizeof(*avr->vcd));
72 memset(avr->vcd, 0, sizeof(*avr->vcd));
74 firmware->tracename[0] ? firmware->tracename: "gtkwave_trace.vcd",
76 firmware->traceperiod >= 1000 ? firmware->traceperiod : 1000);
78 AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", avr->vcd->filename);
79 for (int ti = 0; ti < firmware->tracecount; ti++) {
80 if (firmware->trace[ti].mask == 0xff || firmware->trace[ti].mask == 0) {
82 avr_irq_t * all = avr_iomem_getirq(avr,
83 firmware->trace[ti].addr,
84 firmware->trace[ti].name,
87 AVR_LOG(avr, LOG_ERROR, "ELF: %s: unable to attach trace to address %04x\n",
88 __FUNCTION__, firmware->trace[ti].addr);
90 avr_vcd_add_signal(avr->vcd, all, 8, firmware->trace[ti].name);
94 for (int bi = 0; bi < 8; bi++)
95 if (firmware->trace[ti].mask & (1 << bi))
97 for (int bi = 0; bi < 8; bi++)
98 if (firmware->trace[ti].mask & (1 << bi)) {
99 avr_irq_t * bit = avr_iomem_getirq(avr,
100 firmware->trace[ti].addr,
101 firmware->trace[ti].name,
104 AVR_LOG(avr, LOG_ERROR, "ELF: %s: unable to attach trace to address %04x\n",
105 __FUNCTION__, firmware->trace[ti].addr);
110 avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
114 sprintf(comp, "%s.%d", firmware->trace[ti].name, bi);
115 avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
119 // if the firmware has specified a command register, do NOT start the trace here
120 // the firmware probably knows best when to start/stop it
121 if (!firmware->command_register_addr)
122 avr_vcd_start(avr->vcd);
125 static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uint32_t size)
128 uint8_t tag = *src++;
130 int next = size > 2 + ts ? 2 + ts : size;
131 // printf("elf_parse_mmcu_section %d, %d / %d\n", tag, ts, size);
133 case AVR_MMCU_TAG_FREQUENCY:
134 firmware->frequency =
135 src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
137 case AVR_MMCU_TAG_NAME:
138 strcpy(firmware->mmcu, (char*)src);
140 case AVR_MMCU_TAG_VCC:
142 src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
144 case AVR_MMCU_TAG_AVCC:
146 src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
148 case AVR_MMCU_TAG_AREF:
150 src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
152 case AVR_MMCU_TAG_VCD_TRACE: {
153 uint8_t mask = src[0];
154 uint16_t addr = src[1] | (src[2] << 8);
155 char * name = (char*)src + 3;
156 AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_VCD_TRACE %04x:%02x - %s\n", addr, mask, name);
157 firmware->trace[firmware->tracecount].mask = mask;
158 firmware->trace[firmware->tracecount].addr = addr;
159 strncpy(firmware->trace[firmware->tracecount].name, name,
160 sizeof(firmware->trace[firmware->tracecount].name));
161 firmware->tracecount++;
163 case AVR_MMCU_TAG_VCD_FILENAME: {
164 strcpy(firmware->tracename, (char*)src);
166 case AVR_MMCU_TAG_VCD_PERIOD: {
167 firmware->traceperiod =
168 src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
170 case AVR_MMCU_TAG_SIMAVR_COMMAND: {
171 firmware->command_register_addr = src[0] | (src[1] << 8);
173 case AVR_MMCU_TAG_SIMAVR_CONSOLE: {
174 firmware->console_register_addr = src[0] | (src[1] << 8);
178 src += next - 2; // already incremented
182 int elf_read_firmware(const char * file, elf_firmware_t * firmware)
184 Elf32_Ehdr elf_header; /* ELF header */
185 Elf *elf = NULL; /* Our Elf pointer for libelf */
186 int fd; // File Descriptor
188 if ((fd = open(file, O_RDONLY | O_BINARY)) == -1 ||
189 (read(fd, &elf_header, sizeof(elf_header))) < sizeof(elf_header)) {
190 AVR_LOG(NULL, LOG_ERROR, "could not read %s\n", file);
196 Elf_Data *data_data = NULL,
198 *data_ee = NULL; /* Data Descriptor */
200 memset(firmware, 0, sizeof(*firmware));
202 //int bitesize = ((avr->flashend+1) >> 1) * sizeof(avr_symbol_t);
203 firmware->codesize = 32768;
204 int bitesize = firmware->codesize * sizeof(avr_symbol_t);
205 firmware->codeline = malloc(bitesize);
206 memset(firmware->codeline,0, bitesize);
209 /* this is actually mandatory !! otherwise elf_begin() fails */
210 if (elf_version(EV_CURRENT) == EV_NONE) {
211 /* library out of date - recover from error */
213 // Iterate through section headers again this time well stop when we find symbols
214 elf = elf_begin(fd, ELF_C_READ, NULL);
215 //printf("Loading elf %s : %p\n", file, elf);
217 Elf_Scn *scn = NULL; /* Section Descriptor */
219 while ((scn = elf_nextscn(elf, scn)) != NULL) {
220 GElf_Shdr shdr; /* Section Header */
221 gelf_getshdr(scn, &shdr);
222 char * name = elf_strptr(elf, elf_header.e_shstrndx, shdr.sh_name);
223 // printf("Walking elf section '%s'\n", name);
225 if (!strcmp(name, ".text"))
226 data_text = elf_getdata(scn, NULL);
227 else if (!strcmp(name, ".data"))
228 data_data = elf_getdata(scn, NULL);
229 else if (!strcmp(name, ".eeprom"))
230 data_ee = elf_getdata(scn, NULL);
231 else if (!strcmp(name, ".bss")) {
232 Elf_Data *s = elf_getdata(scn, NULL);
233 firmware->bsssize = s->d_size;
234 } else if (!strcmp(name, ".mmcu")) {
235 Elf_Data *s = elf_getdata(scn, NULL);
236 elf_parse_mmcu_section(firmware, s->d_buf, s->d_size);
237 //printf("%s: avr_mcu_t size %ld / read %ld\n", __FUNCTION__, sizeof(struct avr_mcu_t), s->d_size);
238 // avr->frequency = f_cpu;
241 // When we find a section header marked SHT_SYMTAB stop and get symbols
242 if (shdr.sh_type == SHT_SYMTAB) {
243 // edata points to our symbol table
244 Elf_Data *edata = elf_getdata(scn, NULL);
246 // how many symbols are there? this number comes from the size of
247 // the section divided by the entry size
248 int symbol_count = shdr.sh_size / shdr.sh_entsize;
250 // loop through to grab all symbols
251 for (int i = 0; i < symbol_count; i++) {
252 GElf_Sym sym; /* Symbol */
253 // libelf grabs the symbol data using gelf_getsym()
254 gelf_getsym(edata, i, &sym);
256 // print out the value and size
257 // printf("%08x %08d ", sym.st_value, sym.st_size);
258 if (ELF32_ST_BIND(sym.st_info) == STB_GLOBAL ||
259 ELF32_ST_TYPE(sym.st_info) == STT_FUNC ||
260 ELF32_ST_TYPE(sym.st_info) == STT_OBJECT) {
261 const char * name = elf_strptr(elf, shdr.sh_link, sym.st_name);
264 if (sym.st_value & 0xfff00000) {
268 if (firmware->codeline[sym.st_value >> 1] == NULL) {
269 avr_symbol_t * s = firmware->codeline[sym.st_value >> 1] = malloc(sizeof(avr_symbol_t));
270 s->symbol = strdup(name);
271 s->addr = sym.st_value;
280 avr_symbol_t * last = NULL;
281 for (int i = 0; i < firmware->codesize; i++) {
282 if (!firmware->codeline[i])
283 firmware->codeline[i] = last;
285 last = firmware->codeline[i];
289 firmware->flashsize =
290 (data_text ? data_text->d_size : 0) +
291 (data_data ? data_data->d_size : 0);
292 firmware->flash = malloc(firmware->flashsize);
294 // using unsigned int for output, since there is no AVR with 4GB
296 // hdump("code", data_text->d_buf, data_text->d_size);
297 memcpy(firmware->flash + offset, data_text->d_buf, data_text->d_size);
298 offset += data_text->d_size;
299 AVR_LOG(NULL, LOG_TRACE, "Loaded %u .text\n", (unsigned int)data_text->d_size);
302 // hdump("data", data_data->d_buf, data_data->d_size);
303 memcpy(firmware->flash + offset, data_data->d_buf, data_data->d_size);
304 AVR_LOG(NULL, LOG_TRACE, "Loaded %u .data\n", (unsigned int)data_data->d_size);
305 offset += data_data->d_size;
306 firmware->datasize = data_data->d_size;
309 // hdump("eeprom", data_ee->d_buf, data_ee->d_size);
310 firmware->eeprom = malloc(data_ee->d_size);
311 memcpy(firmware->eeprom, data_ee->d_buf, data_ee->d_size);
312 AVR_LOG(NULL, LOG_TRACE, "Loaded %u .eeprom\n", (unsigned int)data_ee->d_size);
313 firmware->eesize = data_ee->d_size;
315 // hdump("flash", avr->flash, offset);