summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/sbtools/elftosb.c211
1 files changed, 182 insertions, 29 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c
index 58665da16d..38ac0ae32a 100644
--- a/utils/sbtools/elftosb.c
+++ b/utils/sbtools/elftosb.c
@@ -164,28 +164,48 @@ static key_array_t read_keys(const char *key_file, int *num_keys)
164 * Command file parsing 164 * Command file parsing
165 */ 165 */
166 166
167enum cmd_source_type_t
168{
169 CMD_SRC_UNK,
170 CMD_SRC_ELF,
171 CMD_SRC_BIN
172};
173
174struct bin_param_t
175{
176 uint32_t size;
177 void *data;
178};
179
167struct cmd_source_t 180struct cmd_source_t
168{ 181{
169 char *identifier; 182 char *identifier;
170 char *filename; 183 char *filename;
171 struct cmd_source_t *next; 184 struct cmd_source_t *next;
172 /* for later use */ 185 /* for later use */
186 enum cmd_source_type_t type;
187 bool bin_loaded;
173 bool elf_loaded; 188 bool elf_loaded;
174 struct elf_params_t elf; 189 struct elf_params_t elf;
190 struct bin_param_t bin;
175}; 191};
176 192
177enum cmd_inst_type_t 193enum cmd_inst_type_t
178{ 194{
179 CMD_LOAD, 195 CMD_LOAD, /* load image */
180 CMD_JUMP, 196 CMD_JUMP, /* jump at image */
181 CMD_CALL 197 CMD_CALL, /* call image */
198 CMD_LOAD_AT, /* load binary at */
199 CMD_CALL_AT, /* call at address */
200 CMD_JUMP_AT, /* jump at address */
182}; 201};
183 202
184struct cmd_inst_t 203struct cmd_inst_t
185{ 204{
186 enum cmd_inst_type_t type; 205 enum cmd_inst_type_t type;
187 char *identifier; 206 char *identifier;
188 uint32_t argument; 207 uint32_t argument; // for jump, call
208 uint32_t addr; // for 'at'
189 struct cmd_inst_t *next; 209 struct cmd_inst_t *next;
190}; 210};
191 211
@@ -213,6 +233,7 @@ enum lexem_type_t
213 LEX_SEMICOLON, 233 LEX_SEMICOLON,
214 LEX_LBRACE, 234 LEX_LBRACE,
215 LEX_RBRACE, 235 LEX_RBRACE,
236 LEX_RANGLE,
216 LEX_EOF 237 LEX_EOF
217}; 238};
218 239
@@ -276,6 +297,34 @@ static void parse_string(char **ptr, char *end, struct lexem_t *lexem)
276 __parse_string(ptr, end, (void *)&pstr, __parse_string_emit); 297 __parse_string(ptr, end, (void *)&pstr, __parse_string_emit);
277} 298}
278 299
300static void parse_ascii_number(char **ptr, char *end, struct lexem_t *lexem)
301{
302 /* skip ' */
303 (*ptr)++;
304 /* we expect 4 character and then ' */
305 int len = 0;
306 uint32_t value = 0;
307 while(*ptr != end)
308 {
309 if(**ptr != '\'')
310 {
311 value = value << 8 | **ptr;
312 len++;
313 (*ptr)++;
314 }
315 else
316 break;
317 }
318 if(*ptr == end || **ptr != '\'')
319 bug("Unterminated ascii number literal");
320 if(len != 1 && len != 2 && len != 4)
321 bug("Invalid ascii number literal length: only 1, 2 or 4 are valid");
322 /* skip ' */
323 (*ptr)++;
324 lexem->type = LEX_NUMBER;
325 lexem->num = value;
326}
327
279static void parse_number(char **ptr, char *end, struct lexem_t *lexem) 328static void parse_number(char **ptr, char *end, struct lexem_t *lexem)
280{ 329{
281 int base = 10; 330 int base = 10;
@@ -337,9 +386,11 @@ static void next_lexem(char **ptr, char *end, struct lexem_t *lexem)
337 if(**ptr == ')') ret_simple(LEX_RPAREN, 1); 386 if(**ptr == ')') ret_simple(LEX_RPAREN, 1);
338 if(**ptr == '{') ret_simple(LEX_LBRACE, 1); 387 if(**ptr == '{') ret_simple(LEX_LBRACE, 1);
339 if(**ptr == '}') ret_simple(LEX_RBRACE, 1); 388 if(**ptr == '}') ret_simple(LEX_RBRACE, 1);
389 if(**ptr == '>') ret_simple(LEX_RANGLE, 1);
340 if(**ptr == '=') ret_simple(LEX_EQUAL, 1); 390 if(**ptr == '=') ret_simple(LEX_EQUAL, 1);
341 if(**ptr == ';') ret_simple(LEX_SEMICOLON, 1); 391 if(**ptr == ';') ret_simple(LEX_SEMICOLON, 1);
342 if(**ptr == '"') return parse_string(ptr, end, lexem); 392 if(**ptr == '"') return parse_string(ptr, end, lexem);
393 if(**ptr == '\'') return parse_ascii_number(ptr, end, lexem);
343 if(isdigit(**ptr)) return parse_number(ptr, end, lexem); 394 if(isdigit(**ptr)) return parse_number(ptr, end, lexem);
344 if(isalpha(**ptr) || **ptr == '_') return parse_identifier(ptr, end, lexem); 395 if(isalpha(**ptr) || **ptr == '_') return parse_identifier(ptr, end, lexem);
345 bug("Unexpected character '%c' in command file\n", **ptr); 396 bug("Unexpected character '%c' in command file\n", **ptr);
@@ -433,6 +484,8 @@ static struct cmd_file_t *read_command_file(const char *file)
433 bug("invalid command file: ';' expected after string"); 484 bug("invalid command file: ';' expected after string");
434 if(find_source_by_id(cmd_file, src->identifier) != NULL) 485 if(find_source_by_id(cmd_file, src->identifier) != NULL)
435 bug("invalid command file: duplicated source identifier"); 486 bug("invalid command file: duplicated source identifier");
487 /* type filled later */
488 src->type = CMD_SRC_UNK;
436 cmd_file->source_list = src; 489 cmd_file->source_list = src;
437 } 490 }
438 491
@@ -452,9 +505,14 @@ static struct cmd_file_t *read_command_file(const char *file)
452 if(lexem.type != LEX_LPAREN) 505 if(lexem.type != LEX_LPAREN)
453 bug("invalid command file: '(' expected after 'section'"); 506 bug("invalid command file: '(' expected after 'section'");
454 next(); 507 next();
455 if(lexem.type != LEX_NUMBER) 508 /* can be a number or a 4 character long string */
509 if(lexem.type == LEX_NUMBER)
510 {
511 sec->identifier = lexem.num;
512 }
513 else
456 bug("invalid command file: number expected as section identifier"); 514 bug("invalid command file: number expected as section identifier");
457 sec->identifier = lexem.num; 515
458 next(); 516 next();
459 if(lexem.type != LEX_RPAREN) 517 if(lexem.type != LEX_RPAREN)
460 bug("invalid command file: ')' expected after section identifier"); 518 bug("invalid command file: ')' expected after section identifier");
@@ -480,26 +538,62 @@ static struct cmd_file_t *read_command_file(const char *file)
480 else 538 else
481 bug("invalid command file: instruction expected in section"); 539 bug("invalid command file: instruction expected in section");
482 next(); 540 next();
483 if(lexem.type != LEX_IDENTIFIER) 541
484 bug("invalid command file: identifier expected after instruction"); 542 if(inst->type == CMD_LOAD)
485 inst->identifier = lexem.str;
486 if(find_source_by_id(cmd_file, inst->identifier) == NULL)
487 bug("invalid command file: undefined reference to source '%s'", inst->identifier);
488 next();
489 if((inst->type == CMD_CALL || inst->type == CMD_JUMP) && lexem.type == LEX_LPAREN)
490 { 543 {
544 if(lexem.type != LEX_IDENTIFIER)
545 bug("invalid command file: identifier expected after instruction");
546 inst->identifier = lexem.str;
547 if(find_source_by_id(cmd_file, inst->identifier) == NULL)
548 bug("invalid command file: undefined reference to source '%s'", inst->identifier);
491 next(); 549 next();
492 if(lexem.type != LEX_NUMBER) 550 if(lexem.type == LEX_RANGLE)
493 bug("invalid command file: expected numeral expression after ("); 551 {
494 inst->argument = lexem.num; 552 // load at
495 next(); 553 inst->type = CMD_LOAD_AT;
496 if(lexem.type != LEX_RPAREN) 554 next();
497 bug("invalid command file: expected closing brace"); 555 if(lexem.type != LEX_NUMBER)
498 next(); 556 bug("invalid command file: number expected for loading address");
557 inst->addr = lexem.num;
558 next();
559 }
560 if(lexem.type != LEX_SEMICOLON)
561 bug("invalid command file: expected ';' after command");
499 } 562 }
500 if(lexem.type != LEX_SEMICOLON) 563 else if(inst->type == CMD_CALL || inst->type == CMD_JUMP)
501 bug("invalid command file: expected ';' after command"); 564 {
502 565 if(lexem.type == LEX_IDENTIFIER)
566 {
567 inst->identifier = lexem.str;
568 if(find_source_by_id(cmd_file, inst->identifier) == NULL)
569 bug("invalid command file: undefined reference to source '%s'", inst->identifier);
570 next();
571 }
572 else if(lexem.type == LEX_NUMBER)
573 {
574 inst->type = (inst->type == CMD_CALL) ? CMD_CALL_AT : CMD_JUMP_AT;
575 inst->addr = lexem.num;
576 next();
577 }
578 else
579 bug("invalid command file: identifier or number expected after jump/load");
580
581 if(lexem.type == LEX_LPAREN)
582 {
583 next();
584 if(lexem.type != LEX_NUMBER)
585 bug("invalid command file: expected numeral expression after (");
586 inst->argument = lexem.num;
587 next();
588 if(lexem.type != LEX_RPAREN)
589 bug("invalid command file: expected closing brace");
590 next();
591 }
592 if(lexem.type != LEX_SEMICOLON)
593 bug("invalid command file: expected ';' after command");
594 }
595 else
596 bug("die");
503 if(end_list == NULL) 597 if(end_list == NULL)
504 { 598 {
505 sec->inst_list = inst; 599 sec->inst_list = inst;
@@ -589,8 +683,11 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
589 if(src == NULL) 683 if(src == NULL)
590 bug("undefined reference to source '%s'\n", id); 684 bug("undefined reference to source '%s'\n", id);
591 /* avoid reloading */ 685 /* avoid reloading */
592 if(src->elf_loaded) 686 if(src->type == CMD_SRC_ELF && src->elf_loaded)
593 return; 687 return;
688 if(src->type != CMD_SRC_UNK)
689 bug("source '%s' seen both as elf and binary file", id);
690 src->type = CMD_SRC_ELF;
594 int fd = open(src->filename, O_RDONLY); 691 int fd = open(src->filename, O_RDONLY);
595 if(fd < 0) 692 if(fd < 0)
596 bug("cannot open '%s' (id '%s')\n", src->filename, id); 693 bug("cannot open '%s' (id '%s')\n", src->filename, id);
@@ -603,6 +700,32 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
603 bug("error loading elf file '%s' (id '%s')\n", src->filename, id); 700 bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
604} 701}
605 702
703static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)
704{
705 struct cmd_source_t *src = find_source_by_id(cmd_file, id);
706 if(src == NULL)
707 bug("undefined reference to source '%s'\n", id);
708 if(src == NULL)
709 bug("undefined reference to source '%s'\n", id);
710 /* avoid reloading */
711 if(src->type == CMD_SRC_BIN && src->bin_loaded)
712 return;
713 if(src->type != CMD_SRC_UNK)
714 bug("source '%s' seen both as elf and binary file", id);
715 src->type = CMD_SRC_BIN;
716 int fd = open(src->filename, O_RDONLY);
717 if(fd < 0)
718 bug("cannot open '%s' (id '%s')\n", src->filename, id);
719 if(g_debug)
720 printf("Loading BIN file '%s'...\n", src->filename);
721 src->bin.size = lseek(fd, 0, SEEK_END);
722 lseek(fd, 0, SEEK_SET);
723 src->bin.data = xmalloc(src->bin.size);
724 read(fd, src->bin.data, src->bin.size);
725 close(fd);
726 src->bin_loaded = true;
727}
728
606static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) 729static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
607{ 730{
608 struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t)); 731 struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t));
@@ -630,17 +753,31 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
630 struct cmd_inst_t *cinst = csec->inst_list; 753 struct cmd_inst_t *cinst = csec->inst_list;
631 while(cinst) 754 while(cinst)
632 { 755 {
633 load_elf_by_id(cmd_file, cinst->identifier);
634 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
635
636 if(cinst->type == CMD_LOAD) 756 if(cinst->type == CMD_LOAD)
757 {
758 load_elf_by_id(cmd_file, cinst->identifier);
759 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
637 sec->nr_insts += elf_get_nr_sections(elf); 760 sec->nr_insts += elf_get_nr_sections(elf);
761 }
638 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL) 762 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
639 { 763 {
764 load_elf_by_id(cmd_file, cinst->identifier);
765 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
640 if(!elf_get_start_addr(elf, NULL)) 766 if(!elf_get_start_addr(elf, NULL))
641 bug("cannot jump/call '%s' because it has no starting point !\n", cinst->identifier); 767 bug("cannot jump/call '%s' because it has no starting point !\n", cinst->identifier);
642 sec->nr_insts++; 768 sec->nr_insts++;
643 } 769 }
770 else if(cinst->type == CMD_CALL_AT || cinst->type == CMD_JUMP_AT)
771 {
772 sec->nr_insts++;
773 }
774 else if(cinst->type == CMD_LOAD_AT)
775 {
776 load_bin_by_id(cmd_file, cinst->identifier);
777 sec->nr_insts++;
778 }
779 else
780 bug("die");
644 781
645 cinst = cinst->next; 782 cinst = cinst->next;
646 } 783 }
@@ -652,10 +789,9 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
652 cinst = csec->inst_list; 789 cinst = csec->inst_list;
653 while(cinst) 790 while(cinst)
654 { 791 {
655 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
656
657 if(cinst->type == CMD_LOAD) 792 if(cinst->type == CMD_LOAD)
658 { 793 {
794 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
659 struct elf_section_t *esec = elf->first_section; 795 struct elf_section_t *esec = elf->first_section;
660 while(esec) 796 while(esec)
661 { 797 {
@@ -678,10 +814,27 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
678 } 814 }
679 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL) 815 else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL)
680 { 816 {
817 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
681 sec->insts[idx].argument = cinst->argument; 818 sec->insts[idx].argument = cinst->argument;
682 sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL; 819 sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL;
683 sec->insts[idx++].addr = elf->start_addr; 820 sec->insts[idx++].addr = elf->start_addr;
684 } 821 }
822 else if(cinst->type == CMD_JUMP_AT || cinst->type == CMD_CALL_AT)
823 {
824 sec->insts[idx].argument = cinst->argument;
825 sec->insts[idx].inst = (cinst->type == CMD_JUMP_AT) ? SB_INST_JUMP : SB_INST_CALL;
826 sec->insts[idx++].addr = cinst->addr;
827 }
828 else if(cinst->type == CMD_LOAD_AT)
829 {
830 struct bin_param_t *bin = &find_source_by_id(cmd_file, cinst->identifier)->bin;
831 sec->insts[idx].inst = SB_INST_LOAD;
832 sec->insts[idx].addr = cinst->addr;
833 sec->insts[idx].data = bin->data;
834 sec->insts[idx++].size = bin->size;
835 }
836 else
837 bug("die");
685 838
686 cinst = cinst->next; 839 cinst = cinst->next;
687 } 840 }