/* Map file generation
Copyright 2003, 2004, 2005
Craig Franklin
Copyright 2016 Molnár Károly
*/
#include "stdhdr.h"
#include "libgputils.h"
#include "gplink.h"
#include "map.h"
#ifdef STDC_HEADERS
#include <stdarg.h>
#endif
#define SECTION_UNKNOWN 0
#define SECTION_ROMDATA 1
#define SECTION_CODE 2
#define SECTION_IDATA 3
#define SECTION_UDATA 4
struct syms_s {
gp_symbol_t *symbol;
gp_symbol_t *file;
};
typedef struct file_stack {
gp_symbol_t *symbol;
struct file_stack *previous;
} file_stack_t;
/*------------------------------------------------------------------------------------------------*/
static void
_map_line(const char *Format, ...)
{
va_list args;
if (state.map.f) {
if (Format) {
va_start(args, Format);
vfprintf(state.map.f, Format, args);
va_end(args);
}
putc('\n', state.map.f);
}
}
/*------------------------------------------------------------------------------------------------*/
static unsigned
_section_value(const gp_section_t *Section)
{
unsigned value = 0;
if (Section->flags & STYP_TEXT) {
value = SECTION_CODE;
}
else if (Section->flags & STYP_DATA) {
value = SECTION_IDATA;
}
else if (Section->flags & (STYP_BSS | STYP_OVERLAY)) {
value = SECTION_UDATA;
}
else if (Section->flags & STYP_DATA_ROM) {
value = SECTION_ROMDATA;
}
else {
value = SECTION_UNKNOWN;
}
return value;
}
/*------------------------------------------------------------------------------------------------*/
static int
_cmp_sections(const void *A, const void *B)
{
gp_section_t *section_a = *((gp_section_t **)A);
gp_section_t *section_b = *((gp_section_t **)B);
unsigned value_a = _section_value(section_a);
unsigned value_b = _section_value(section_b);
if (value_a < value_b) {
return -1;
}
if (value_a > value_b) {
return 1;
}
if (section_a->address < section_b->address) {
return -1;
}
if (section_a->address > section_b->address) {
return 1;
}
return 0;
}
/*------------------------------------------------------------------------------------------------*/
static void _write_sections() {
unsigned num_sections = state.object->section_list.num_nodes;
gp_section_t**section_list = new gp_section_t*[num_sections];
gp_section_t*section = state.object->section_list.first;
unsigned i;
for (i = 0; i < num_sections; i++) {
assert(section);
section_list[i] = section;
section = section->next;
}
qsort((void *)section_list, num_sections, sizeof(gp_section_t *), _cmp_sections);
_map_line(" Section Info");
_map_line(" Section Type Address Location Size(Bytes)");
_map_line(" --------- --------- --------- --------- ---------");
for (i = 0; i < num_sections; i++) {
int org_to_byte_shift = state.pclass->org_to_byte_shift;
section = section_list[i];
const char*type;
switch (_section_value(section)) {
case SECTION_ROMDATA:
type = "romdata";
break;
case SECTION_CODE:
type = "code";
break;
case SECTION_IDATA:
type = "idata";
break;
case SECTION_UDATA:
type = "udata";
break;
case SECTION_UNKNOWN:
default:
type = "UNKNOWN";
}
const char*location;
if (section->flags & STYP_ROM_AREA) location = "program";
else {
location = "data";
org_to_byte_shift = 0;
}
assert(section->name);
if (section->size != 0) {
_map_line("%25s %10s 0x%06x %10s 0x%06x", section->name, type,
gp_insn_from_byte(org_to_byte_shift, section->address), location, section->size);
}
}
free(section_list);
_map_line(NULL);
_map_line(NULL);
_map_line(NULL);
}
/*------------------------------------------------------------------------------------------------*/
static void
_write_program_memory(void)
{
gp_section_t *section = NULL;
int prog_size = 0;
_map_line(" Program Memory Usage");
_map_line(" Start End");
_map_line(" --------- ---------");
section = state.object->section_list.first;
while (section) {
if ((section->flags & STYP_ROM_AREA) && (section->size > 0)) {
_map_line(" 0x%06x 0x%06x",
gp_processor_insn_from_byte_c(state.pclass, section->address),
gp_processor_insn_from_byte_c(state.pclass, section->address + section->size - 1));
prog_size += section->size;
}
section = section->next;
}
_map_line(" %d program addresses used",
gp_processor_insn_from_byte_c(state.pclass, prog_size));
/*
_map_line(" %d out of %d program addresses used, program memory utilization is %d%%",
gp_processor_insn_from_byte_c(state.pclass, prog_size),
state.processor->prog_mem_size, state.processor->prog_mem_size * 100 / prog_size);
*/
_map_line(NULL);
_map_line(NULL);
_map_line(NULL);
}
/*------------------------------------------------------------------------------------------------*/
static file_stack_t* _push_file(file_stack_t *Stack, gp_symbol_t *Symbol) {
/* allocate memory for the pnew stack */
file_stack_t*pnew = new file_stack_t;
pnew->previous = Stack;
pnew->symbol = Symbol;
return pnew;
}
/*------------------------------------------------------------------------------------------------*/
static file_stack_t* _pop_file(file_stack_t *Stack) {
if (Stack) {
file_stack_t*old = Stack;
Stack = Stack->previous;
delete old;
}
return Stack;
}
/*------------------------------------------------------------------------------------------------*/
static int _cmp_name(const void *P1, const void *P2) {
return strcmp(((struct syms_s *)P1)->symbol->name, ((struct syms_s *)P2)->symbol->name);
}
/*------------------------------------------------------------------------------------------------*/
static int _cmp_address(const void *P1, const void *P2) {
return ((struct syms_s *)P1)->symbol->value - ((struct syms_s *)P2)->symbol->value;
}
/*------------------------------------------------------------------------------------------------*/
static void _write_symbols() {
const gp_symbol_t *sm;
int num_syms;
int i;
file_stack_t *stack = NULL;
syms_s*syms = new syms_s[state.object->num_symbols];
num_syms = 0;
FOR(gp_symbol_list_t,symbol,state.object->symbol_list) {
if (symbol->pclass == C_FILE) stack = _push_file(stack, &*symbol);
else if (symbol->pclass == C_EOF) stack = _pop_file(stack);
else if (symbol->section_number > N_UNDEF && symbol->pclass != C_SECTION) {
if (!stack) syms[num_syms].file = 0;
/* the symbol is not between a .file/.eof pair */
else {
syms[num_syms].file = stack->symbol;
assert(syms[num_syms].file);
assert(syms[num_syms].file->aux_list.first);
}
assert(symbol->section);
assert(symbol->name);
syms[num_syms].symbol = &*symbol;
++num_syms;
assert(num_syms <= (int)state.object->num_symbols);
}
}
qsort(syms, num_syms, sizeof(struct syms_s), _cmp_name);
_map_line(" Symbols - Sorted by Name");
_map_line(" Name Address Location Storage File");
_map_line(" --------- --------- --------- --------- ---------");
for (i = 0; i < num_syms; ++i) {
sm = syms[i].symbol;
_map_line("%25s 0x%06x %10s %10s %s", sm->name, sm->value,
(sm->section->flags & STYP_ROM_AREA) ? "program" : "data",
(sm->pclass == C_EXT) ? "extern" : "static",
(syms[i].file) ? syms[i].file->aux_list.first->_aux_symbol._aux_file.filename : "");
}
_map_line(NULL);
_map_line(NULL);
_map_line(NULL);
qsort(syms, num_syms, sizeof(struct syms_s), _cmp_address);
_map_line(" Symbols - Sorted by Address");
_map_line(" Name Address Location Storage File");
_map_line(" --------- --------- --------- --------- ---------");
for (i = 0; i < num_syms; ++i) {
sm = syms[i].symbol;
_map_line("%25s 0x%06x %10s %10s %s", sm->name, sm->value,
(sm->section->flags & STYP_ROM_AREA) ? "program" : "data",
(sm->pclass == C_EXT) ? "extern" : "static",
(syms[i].file) ? syms[i].file->aux_list.first->_aux_symbol._aux_file.filename : "");
}
free(syms);
_map_line(NULL);
_map_line(NULL);
}
/*------------------------------------------------------------------------------------------------*/
void make_map(void) {
if (gp_num.errors || state.map_file == OUT_SUPPRESS) {
unlink(state.map_file_name);
return;
}
state.map.f = fopen(state.map_file_name, "wt");
if (state.map.f == NULL) {
perror(state.map_file_name);
exit(1);
}
_map_line("%s", GPLINK_VERSION_STRING);
_map_line("Map File - Created %s", state.start_date);
_map_line(NULL);
/* write sections */
_write_sections();
/* program memory usage */
_write_program_memory();
/* write symbols */
_write_symbols();
fclose(state.map.f);
}
Vorgefundene Kodierung: UTF-8 | 0
|