Source file: /~heha/hs/gputils64-210929.zip/gplink/map.cpp

/* 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);
}
Detected encoding: UTF-80