FreeCalypso > hg > freecalypso-reveng
view leo-obj/tool/richsym.c @ 148:13cc7e19ecec
tiobjd disasm -g: support -b as well
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 29 Apr 2014 06:45:45 +0000 |
parents | 70631c246df0 |
children | fdf3137c703a |
line wrap: on
line source
/* * Code for working with the "rich" symbolic info * present in TI's GPF libraries */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "intstruct.h" #include "coffconst.h" #include "globals.h" extern unsigned get_u16(), get_u32(); extern char *storage_class_to_string(); int richsym_print_bitsize; static int try_typedef_hack(struct_sym) struct internal_syment *struct_sym; { unsigned tpdef_cand; struct internal_syment *tpdef_sym; if (!struct_sym->aux) return(0); tpdef_cand = get_u32(struct_sym->aux + 12); if (tpdef_cand >= nsymtab) return(0); tpdef_sym = symtab[tpdef_cand]; if (!tpdef_sym) return(0); if (tpdef_sym->class != C_TPDEF) return(0); if (tpdef_sym->type != struct_sym->type) return(0); if (tpdef_sym->name[0] != '_') return(0); if (!tpdef_sym->aux) return(0); if (get_u32(tpdef_sym->aux) != struct_sym->number) return(0); struct_sym->struct_name = tpdef_sym->name + 1; return(1); } static void preen_strtag_sym(sym, kw, expect_type) struct internal_syment *sym; char *kw; { char *buf; int isund, len; isund = (sym->name[0] == '_'); len = strlen(kw) + 1 + strlen(sym->name) + 1; if (isund) len--; else len += 2; buf = malloc(len); if (!buf) { perror("malloc"); exit(1); } if (isund) sprintf(buf, "%s %s", kw, sym->name + 1); else sprintf(buf, "%s \"%s\"", kw, sym->name); sym->struct_name = buf; sym->struct_name_raw = buf; if (sym->type != expect_type) { fprintf(stderr, "warning: type/class mismatch on tag symbol #%u\n", sym->number); return; } if (isund) return; try_typedef_hack(sym); } richsym_initial_preen() { unsigned n; struct internal_syment *sym; for (n = 0; n < nsymtab; n++) { sym = symtab[n]; if (!sym) continue; switch (sym->class) { case C_STRTAG: preen_strtag_sym(sym, "struct", T_STRUCT); continue; case C_UNTAG: preen_strtag_sym(sym, "union", T_UNION); continue; case C_ENTAG: preen_strtag_sym(sym, "enum", T_ENUM); continue; } } } char * get_struct_type_name(idx, expect_class, is_typedef) unsigned idx; { struct internal_syment *sym; if (idx >= nsymtab) { inv_idx: fprintf(stderr, "error: ref to invalid syment #%u for struct tag\n", idx); exit(1); } sym = symtab[idx]; if (!sym) goto inv_idx; if (sym->class != expect_class) { fprintf(stderr, "error: ref to syment #%u for struct tag, class != %s\n", idx, storage_class_to_string(expect_class, 0)); exit(1); } if (is_typedef) return(sym->struct_name_raw); else return(sym->struct_name); } char * get_base_type_of_syment(sym, is_typedef) struct internal_syment *sym; { switch (sym->type & 0xF) { case T_VOID: return("void"); case T_CHAR: if (is_typedef) return("signed char"); else return("char"); case T_SHORT: return("short"); case T_INT: return("int"); case T_LONG: return("long"); case T_FLOAT: return("float"); case T_DOUBLE: return("double"); case T_STRUCT: return get_struct_type_name(get_u32(sym->aux), C_STRTAG, is_typedef); case T_UNION: return get_struct_type_name(get_u32(sym->aux), C_UNTAG, is_typedef); case T_ENUM: return get_struct_type_name(get_u32(sym->aux), C_ENTAG, is_typedef); case T_UCHAR: if (is_typedef) return("unsigned char"); else return("u_char"); case T_USHORT: if (is_typedef) return("unsigned short"); else return("u_short"); case T_UINT: return("unsigned"); case T_ULONG: if (is_typedef) return("unsigned long"); else return("u_long"); default: return("__unknown_base_type"); } } richsym_print_in_c(prefix, sym, is_typedef) char *prefix; struct internal_syment *sym; { char *base_type, *s1, *s2; int dertype, last_ptr, narray; base_type = get_base_type_of_syment(sym, is_typedef); dertype = sym->type >> 4; s1 = malloc(strlen(sym->name)); if (!s1) { perror("malloc"); exit(1); } strcpy(s1, sym->name + 1); last_ptr = 0; narray = 0; for (; dertype; dertype >>= 2) { switch (dertype & 3) { case DT_NON: fprintf(stderr, "error: symbol #%u: DT_NON followed by more derived types\n", sym->number); exit(1); case DT_PTR: s2 = malloc(strlen(s1) + 2); if (!s2) { perror("malloc"); exit(1); } sprintf(s2, "*%s", s1); free(s1); s1 = s2; last_ptr = 1; continue; } if (last_ptr) { s2 = malloc(strlen(s1) + 3); if (!s2) { perror("malloc"); exit(1); } sprintf(s2, "(%s)", s1); free(s1); s1 = s2; } switch (dertype & 3) { case DT_FCN: s2 = malloc(strlen(s1) + 3); if (!s2) { perror("malloc"); exit(1); } sprintf(s2, "%s()", s1); free(s1); s1 = s2; break; case DT_ARY: if (narray >= 4) { fprintf(stderr, "error: symbol #%u: too many [] types\n", sym->number); exit(1); } s2 = malloc(strlen(s1) + 8); if (!s2) { perror("malloc"); exit(1); } sprintf(s2, "%s[%u]", s1, get_u16(sym->aux + 8 + narray * 2)); free(s1); s1 = s2; narray++; break; default: fprintf(stderr, "BUG in richsym_print_in_c(): bad derived type\n"); exit(1); } last_ptr = 0; } printf("%s%s %s;", prefix, base_type, s1); free(s1); if (richsym_print_bitsize && (sym->type & 0x30) != 0x20) printf("\t/* %u bits */", get_u32(sym->aux + 4)); putchar('\n'); } cmd_ctypes(argc, argv) char **argv; { int c; unsigned n; struct internal_syment *sym; while ((c = getopt(argc, argv, "b")) != EOF) switch (c) { case 'b': richsym_print_bitsize++; continue; default: /* error msg already printed */ exit(1); } get_int_section_table(); get_int_symbol_table(); richsym_initial_preen(); for (n = 0; n < nsymtab; n++) { sym = symtab[n]; if (!sym) continue; switch (sym->class) { case C_FILE: printf("/* from %s */\n", sym->name); continue; case C_STRTAG: case C_UNTAG: case C_ENTAG: printf("%s {", sym->struct_name_raw); if (richsym_print_bitsize && sym->aux) printf("\t/* %u bits */", get_u32(sym->aux+4)); putchar('\n'); continue; case C_EOS: fputs("};", stdout); if (richsym_print_bitsize && sym->aux) printf("\t/* %u bits */", get_u32(sym->aux+4)); putchar('\n'); continue; case C_MOS: case C_MOU: case C_MOE: case C_TPDEF: break; default: continue; } if (sym->name[0] != '_') { printf( "/* symbol #%u of class %s has no leading underscore */\n", sym->number, storage_class_to_string(sym->class, 0)); continue; } if (!sym->aux && sym->class != C_MOE) { printf( "/* symbol #%u of class %s has no aux record */\n", sym->number, storage_class_to_string(sym->class, 0)); continue; } switch (sym->class) { case C_MOS: case C_MOU: if (sym->scnum != -1) printf("\t/* MOS/MOU section != ABS! */\n"); else if (richsym_print_bitsize >= 2) printf("\t/* offset: %u bits */\n", sym->value); richsym_print_in_c("\t", sym, 0); continue; case C_MOE: if (sym->scnum != -1) { printf("\t/* MOE section != ABS! */\n"); continue; } printf("\t%s = %u;", sym->name + 1, sym->value); if (sym->value >= 10) printf("\t/* 0x%x */", sym->value); putchar('\n'); continue; case C_TPDEF: richsym_print_in_c("typedef ", sym, !(sym->type & 0xFFF0)); continue; } } exit(0); }