Line 23... |
Line 23... |
#include <stdlib.h>
|
#include <stdlib.h>
|
|
|
#include "parse.h"
|
#include "parse.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "arch.h"
|
#include "arch.h"
|
|
#include "coff.h"
|
|
|
#define MAXLINE_LEN 18000
|
#define MAXLINE_LEN 18000
|
|
|
|
extern char *disassembled;
|
|
|
/* Unused mem memory marker. It is used when allocating program and data memory
|
/* Unused mem memory marker. It is used when allocating program and data memory
|
during parsing */
|
during parsing */
|
unsigned int freemem;
|
unsigned int freemem;
|
|
|
int nonempty(char *line)
|
int nonempty(char *line)
|
Line 148... |
Line 151... |
void adddataspace(char *num)
|
void adddataspace(char *num)
|
{
|
{
|
freemem += atol(num);
|
freemem += atol(num);
|
}
|
}
|
|
|
void addlabel(char *label)
|
void addlabel(char *label, unsigned long freemem)
|
{
|
{
|
if (strstr(label, LABELEND_CHAR)) {
|
struct label_entry **tmp;
|
*strstr(label, LABELEND_CHAR) = '\0';
|
|
strcpy(mem[freemem].label, label);
|
printf("adding label %s at %x\n", label, freemem);
|
}
|
tmp = &mem[freemem].label;
|
|
for (; *tmp; tmp = &((*tmp)->next));
|
|
*tmp = malloc(sizeof(**tmp));
|
|
(*tmp)->name = malloc(strlen(label)+1);
|
|
strcpy((*tmp)->name, label);
|
|
(*tmp)->next = NULL;
|
|
|
return;
|
return;
|
}
|
}
|
|
|
|
char null_str[1] = "\0";
|
|
|
void addprogram(char *insn, char *operands)
|
void addprogram(char *insn, char *operands)
|
{
|
{
|
#ifdef __HALF_WORD_INSN__
|
|
int h_insn_is_word_flag=0;
|
int h_insn_is_word_flag=0;
|
char insn_first2_char[3];
|
char insn_first2_char[3];
|
|
|
strcpy(mem[freemem].insn, insn);
|
debug("addprogram 1\n");
|
|
if (!mem[freemem].insn) {
|
|
mem[freemem].insn = malloc(sizeof(*mem[freemem].insn));
|
|
mem[freemem].insn->insn = null_str;
|
|
mem[freemem].insn->op1 = null_str;
|
|
mem[freemem].insn->op2 = null_str;
|
|
mem[freemem].insn->op3 = null_str;
|
|
mem[freemem].insn->op4 = null_str;
|
|
} else {
|
|
printf("internal error: reloading the same location\n");
|
|
exit(1);
|
|
}
|
|
debug("addprogram 2\n");
|
|
|
|
mem[freemem].insn->insn = malloc(strlen(insn)+1);
|
|
|
|
#ifdef OR16
|
|
|
|
strcpy(mem[freemem].insn->insn, insn);
|
|
printf("half:%s:\n", insn);
|
insn_first2_char[0]=insn[0];
|
insn_first2_char[0]=insn[0];
|
insn_first2_char[1]=insn[1];
|
insn_first2_char[1]=insn[1];
|
insn_first2_char[2]='\0';
|
insn_first2_char[2]='\0';
|
|
debug("addprogram 3\n");
|
|
|
if(strcmp("h.", insn_first2_char) == 0) {
|
if(strcmp("h.", insn_first2_char) == 0) {
|
if(strcmp("h.load32u", insn) == 0 ||
|
if(strcmp("h.load32u", insn) == 0 ||
|
strcmp("h.load16u", insn) == 0 ||
|
strcmp("h.load16u", insn) == 0 ||
|
strcmp("h.load8u", insn) == 0 ||
|
strcmp("h.load8u", insn) == 0 ||
|
Line 195... |
Line 224... |
}
|
}
|
else {
|
else {
|
h_insn_is_word_flag = 0; /* not h.xxx insn */
|
h_insn_is_word_flag = 0; /* not h.xxx insn */
|
}
|
}
|
#else
|
#else
|
strcpy(mem[freemem].insn, insn);
|
debug("addprogram 4\n");
|
|
strcpy(mem[freemem].insn->insn, insn);
|
|
debug("addprogram 5\n");
|
#endif
|
#endif
|
|
|
/* op1 */
|
/* op1 */
|
if (*operands)
|
if (*operands) {
|
strcpy(mem[freemem].op1, operands);
|
mem[freemem].insn->op1 = malloc(strlen(operands)+1);
|
if (strstr(mem[freemem].op1, OPERAND_DELIM)) {
|
strcpy(mem[freemem].insn->op1, operands);
|
operands = strstr(mem[freemem].op1, OPERAND_DELIM);
|
}
|
|
|
|
debug("addprogram 6\n");
|
|
debug("operands:%s\n", operands);
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
debug("addprogram 6a\n");
|
|
operands = strstr(mem[freemem].insn->op1, OPERAND_DELIM);
|
*operands = '\0';
|
*operands = '\0';
|
operands++;
|
operands++;
|
} else {
|
} else {
|
#ifdef __HALF_WORD_INSN__
|
debug("addprogram 6b\n");
|
|
#ifdef OR16
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
#else
|
#else
|
freemem += 4;
|
freemem += 4;
|
#endif
|
#endif
|
return;
|
return;
|
}
|
}
|
|
|
|
debug("addprogram 7\n");
|
/* op2 */
|
/* op2 */
|
if (*operands)
|
if (*operands) {
|
strcpy(mem[freemem].op2, operands);
|
mem[freemem].insn->op2 = malloc(strlen(operands)+1);
|
if (strstr(mem[freemem].op2, OPERAND_DELIM)) {
|
strcpy(mem[freemem].insn->op2, operands);
|
operands = strstr(mem[freemem].op2, OPERAND_DELIM);
|
}
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
operands = strstr(mem[freemem].insn->op2, OPERAND_DELIM);
|
*operands = '\0';
|
*operands = '\0';
|
operands++;
|
operands++;
|
} else {
|
} else {
|
#ifdef __HALF_WORD_INSN__
|
#ifdef OR16
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
#else
|
#else
|
freemem += 4;
|
freemem += 4;
|
#endif
|
#endif
|
return;
|
return;
|
}
|
}
|
|
|
|
debug("addprogram 8\n");
|
/* op3 */
|
/* op3 */
|
if (*operands)
|
if (*operands) {
|
strcpy(mem[freemem].op3, operands);
|
mem[freemem].insn->op3 = malloc(strlen(operands)+1);
|
if (strstr(mem[freemem].op3, OPERAND_DELIM)) {
|
strcpy(mem[freemem].insn->op3, operands);
|
operands = strstr(mem[freemem].op3, OPERAND_DELIM);
|
}
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
operands = strstr(mem[freemem].insn->op3, OPERAND_DELIM);
|
*operands = '\0';
|
*operands = '\0';
|
operands++;
|
operands++;
|
} else {
|
} else {
|
#ifdef __HALF_WORD_INSN__
|
#ifdef OR16
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
#else
|
#else
|
freemem += 4;
|
freemem += 4;
|
#endif
|
#endif
|
return;
|
return;
|
}
|
}
|
|
|
/* op4 */
|
/* op4 */
|
if (*operands)
|
if (*operands) {
|
strcpy(mem[freemem].op4, operands);
|
mem[freemem].insn->op4 = malloc(strlen(operands)+1);
|
if (strstr(mem[freemem].op4, OPERAND_DELIM)) {
|
strcpy(mem[freemem].insn->op4, operands);
|
operands = strstr(mem[freemem].op4, OPERAND_DELIM);
|
}
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
operands = strstr(mem[freemem].insn->op4, OPERAND_DELIM);
|
*operands = '\0';
|
*operands = '\0';
|
operands++;
|
operands++;
|
}
|
}
|
|
|
#ifdef __HALF_WORD_INSN__
|
#ifdef OR16
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
#else
|
#else
|
freemem += 4;
|
freemem += 4;
|
#endif
|
#endif
|
return;
|
return;
|
Line 293... |
Line 339... |
if (strlen(item) == 0)
|
if (strlen(item) == 0)
|
return;
|
return;
|
|
|
/* Is this item a label? If yes, add it to the label table and return immediately. */
|
/* Is this item a label? If yes, add it to the label table and return immediately. */
|
if (strstr(item, LABELEND_CHAR)) {
|
if (strstr(item, LABELEND_CHAR)) {
|
addlabel(item);
|
*strstr(item, LABELEND_CHAR) = '\0';
|
|
addlabel(item, freemem);
|
return;
|
return;
|
}
|
}
|
|
|
/* Is this item a .directive? If yes, check for some supported
|
/* Is this item a .directive? If yes, check for some supported
|
and then return (even if unsupported found). */
|
and then return (even if unsupported found). */
|
if (item[0] == DIRECTIVE_CHAR) {
|
if (item[0] == DIRECTIVE_CHAR) {
|
if ((strcmp(item, ".align") == 0) && (freemem % 4)) {
|
if (strcmp(item, ".align") == 0) {
|
freemem &= -4; /* e.g. 0xfffffffc */
|
int align = atoi(item2);
|
freemem += 4; /* always align to word */
|
if (!(freemem % align))
|
|
return;
|
|
freemem &= -align;
|
|
freemem += align;
|
return;
|
return;
|
} else
|
} else
|
if (strcmp(item, ".ascii") == 0) {
|
if (strcmp(item, ".ascii") == 0) {
|
adddatastr(strstr(inputline, "\""));
|
adddatastr(strstr(inputline, "\""));
|
return;
|
return;
|
Line 330... |
Line 380... |
return;
|
return;
|
}
|
}
|
|
|
/* This item can only be an instruction. Get all operands
|
/* This item can only be an instruction. Get all operands
|
and add everything to mem array but as a program. */
|
and add everything to mem array but as a program. */
|
|
debug("%x: ", freemem);
|
addprogram(item, item2);
|
addprogram(item, item2);
|
|
|
/* Also do static, single stats. */
|
/* Also do static, single stats. */
|
addsstats(item, 0, 1);
|
addsstats(item, 0, 1);
|
|
|
return;
|
return;
|
|
|
}
|
}
|
|
|
|
/* Load big-endian COFF file. At the moment it doesn't load symbols yet. */
|
|
|
|
void readfile_coff(char *filename, short sections)
|
|
{
|
|
FILE *inputfs;
|
|
char inputbuf[4];
|
|
unsigned long insn;
|
|
signed long tstart, tsize, dstart, dsize;
|
|
COFF_AOUTHDR coffaouthdr;
|
|
struct COFF_scnhdr coffscnhdr;
|
|
int len;
|
|
char item[MAXLINE_LEN];
|
|
char item2[MAXLINE_LEN];
|
|
|
|
|
|
if (!(inputfs = fopen(filename, "r"))) {
|
|
perror("readfile_coff");
|
|
exit(1);
|
|
}
|
|
|
|
if (fseek(inputfs, sizeof(struct COFF_filehdr), SEEK_SET) == -1) {
|
|
fclose(inputfs);
|
|
perror("readfile_coff");
|
|
exit(1);
|
|
}
|
|
|
|
if (fread(&coffaouthdr, sizeof(coffaouthdr), 1, inputfs) != 1) {
|
|
fclose(inputfs);
|
|
perror("readfile_coff");
|
|
exit(1);
|
|
}
|
|
|
|
tstart = COFF_LONG_H(coffaouthdr.text_start);
|
|
dstart = COFF_LONG_H(coffaouthdr.data_start);
|
|
tsize = COFF_LONG_H(coffaouthdr.tsize);
|
|
dsize = COFF_LONG_H(coffaouthdr.dsize);
|
|
printf("text_start: %x, ", tstart);
|
|
printf("tsize: %x, ", tsize);
|
|
printf("data_start: %x, ", dstart);
|
|
printf("dsize: %x\n", dsize);
|
|
|
|
while(sections--) {
|
|
if (fread(&coffscnhdr, sizeof(struct COFF_scnhdr), 1, inputfs) != 1) {
|
|
fclose(inputfs);
|
|
perror("readfile_coff");
|
|
exit(1);
|
|
}
|
|
printf("Section: %s,", coffscnhdr.s_name);
|
|
printf(" size: 0x%.4x,", COFF_LONG_H(coffscnhdr.s_size));
|
|
printf(" scnptr: 0x%.4x\n", COFF_LONG_H(coffscnhdr.s_scnptr));
|
|
}
|
|
|
|
/* loading .text section */
|
|
while ((len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) {
|
|
insn = COFF_LONG_H(inputbuf);
|
|
len = disassemble_insn(insn);
|
|
if (len == 2) {
|
|
fseek(inputfs, -2, SEEK_CUR);
|
|
printf("readfile_coff: %x 0x%x ", tsize, insn >> 16);
|
|
}
|
|
else
|
|
printf("readfile_coff: %x 0x%x ", tsize, insn);
|
|
printf("%s\n", disassembled);
|
|
strtoken(disassembled, item, 1); /* opcode */
|
|
strtoken(disassembled, item2, 2); /* all the remaining one/two/three operands */
|
|
addprogram(item, item2);
|
|
tsize -= len;
|
|
if (tsize <= 0)
|
|
break;
|
|
}
|
|
fclose(inputfs);
|
|
printf("Finished loading COFF.\n");
|
|
return;
|
|
}
|
|
|
|
/* Load symbols from big-endian COFF file. */
|
|
|
|
void readsyms_coff(char *filename, unsigned long symptr, long syms)
|
|
{
|
|
FILE *inputfs;
|
|
struct COFF_syment coffsymhdr;
|
|
|
|
|
|
if (!(inputfs = fopen(filename, "r"))) {
|
|
perror("readsyms_coff");
|
|
exit(1);
|
|
}
|
|
|
|
if (fseek(inputfs, symptr, SEEK_SET) == -1) {
|
|
fclose(inputfs);
|
|
perror("readsyms_coff");
|
|
exit(1);
|
|
}
|
|
|
|
while(syms--) {
|
|
if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) {
|
|
fclose(inputfs);
|
|
perror("readsyms_coff");
|
|
exit(1);
|
|
}
|
|
printf("Symbol: %s,", coffsymhdr.e.e_name);
|
|
printf(" val: 0x%.8x,", COFF_LONG_H(coffsymhdr.e_value));
|
|
printf(" auxs: %c\n", coffsymhdr.e_numaux);
|
|
if (strlen(coffsymhdr.e.e_name))
|
|
addlabel(coffsymhdr.e.e_name, COFF_LONG_H(coffsymhdr.e_value));
|
|
}
|
|
|
|
fclose(inputfs);
|
|
printf("Finished loading symbols.\n");
|
|
return;
|
|
}
|
|
|
/* Load file and hand over every line to parse routine. */
|
/* Load file and hand over every line to parse routine. */
|
|
|
void readfile(char *filename)
|
void readfile_assembly(char *filename)
|
{
|
{
|
FILE *inputfs;
|
FILE *inputfs;
|
char inputbuf[MAXLINE_LEN];
|
char inputbuf[MAXLINE_LEN];
|
char *status;
|
char *status;
|
|
|
if ((inputfs = fopen(filename, "r"))) {
|
if (!(inputfs = fopen(filename, "r"))) {
|
|
perror("readfile_assembly");
|
|
exit(1);
|
|
}
|
|
|
while ((status = fgets(inputbuf, sizeof(inputbuf), inputfs))) {
|
while ((status = fgets(inputbuf, sizeof(inputbuf), inputfs))) {
|
if (nonempty(inputbuf))
|
if (nonempty(inputbuf))
|
parseline(inputbuf);
|
parseline(inputbuf);
|
}
|
}
|
fclose(inputfs);
|
fclose(inputfs);
|
|
|
|
return;
|
}
|
}
|
else
|
|
perror("readfile");
|
|
|
|
|
/* Identify file type and call appropriate readfile_X routine. It only
|
|
handles orX-coff-big executables at the moment. */
|
|
|
|
void identifyfile(char *filename)
|
|
{
|
|
FILE *inputfs;
|
|
struct COFF_filehdr coffhdr;
|
|
size_t len;
|
|
|
|
if (!(inputfs = fopen(filename, "r"))) {
|
|
perror("identifyfile");
|
|
exit(1);
|
|
}
|
|
|
|
if (fread(&coffhdr, sizeof(coffhdr), 1, inputfs) == 1) {
|
|
if (COFF_SHORT_H(coffhdr.f_magic) == 0x17a) {
|
|
unsigned long opthdr_size;
|
|
printf("COFF magic: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_magic));
|
|
printf("COFF flags: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_flags));
|
|
printf("COFF symptr: 0x%.8x\n", COFF_LONG_H(coffhdr.f_symptr));
|
|
if ((COFF_SHORT_H(coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC) {
|
|
printf("This COFF is not an executable.\n");
|
|
exit(1);
|
|
}
|
|
opthdr_size = COFF_SHORT_H(coffhdr.f_opthdr);
|
|
if (opthdr_size != sizeof(COFF_AOUTHDR)) {
|
|
printf("COFF optional header is missing or not recognized.\n");
|
|
printf("COFF f_opthdr: 0x%.2x\n", opthdr_size);
|
|
exit(1);
|
|
}
|
|
fclose(inputfs);
|
|
readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns));
|
|
readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), COFF_LONG_H(coffhdr.f_nsyms));
|
return;
|
return;
|
}
|
}
|
|
else {
|
|
printf("Not COFF, trying to load as assembly.\n");
|
|
fclose(inputfs);
|
|
readfile_assembly(filename);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
perror("identifyfile");
|
|
|
|
fclose(inputfs);
|
|
|
|
return;
|
|
}
|
|
|
void loadcode(char *filename)
|
void loadcode(char *filename)
|
{
|
{
|
freemem = 0;
|
freemem = 0;
|
memset(mem, 0, sizeof(mem));
|
memset(mem, 0, sizeof(mem));
|
readfile(filename);
|
identifyfile(filename);
|
return;
|
return;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|