Logo Search packages:      
Sourcecode: yasm version File versions  Download package

section.c

/*
 * Section utility functions
 *
 *  Copyright (C) 2001  Peter Johnson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#define YASM_LIB_INTERNAL
#include "util.h"
/*@unused@*/ RCSID("$Id: section.c 1154 2004-10-08 07:22:10Z peter $");

#include "coretype.h"
#include "valparam.h"
#include "assocdat.h"

#include "linemgr.h"
#include "errwarn.h"
#include "intnum.h"
#include "expr.h"
#include "symrec.h"

#include "bytecode.h"
#include "section.h"
#include "objfmt.h"

#include "bc-int.h"


struct yasm_object {
    yasm_symtab   *symtab;
    yasm_linemap *linemap;

    /*@reldef@*/ STAILQ_HEAD(yasm_sectionhead, yasm_section) sections;
};

struct yasm_section {
    /*@reldef@*/ STAILQ_ENTRY(yasm_section) link;

    /*@dependent@*/ yasm_object *object;    /* Pointer to parent object */

    enum { SECTION_GENERAL, SECTION_ABSOLUTE } type;

    union {
      /* SECTION_GENERAL data */
      struct general {
          /*@owned@*/ char *name;   /* strdup()'ed name (given by user) */
      } general;
    } data;

    /* associated data; NULL if none */
    /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;

    /*@owned@*/ yasm_expr *start;   /* Starting address of section contents */

    unsigned long opt_flags;  /* storage for optimizer flags */

    int res_only;       /* allow only resb family of bytecodes? */

    /* the bytecodes for the section's contents */
    /*@reldef@*/ STAILQ_HEAD(yasm_bytecodehead, yasm_bytecode) bcs;

    /* the relocations for the section */
    /*@reldef@*/ STAILQ_HEAD(yasm_relochead, yasm_reloc) relocs;

    void (*destroy_reloc) (/*@only@*/ void *reloc);
};

static void yasm_section_destroy(/*@only@*/ yasm_section *sect);


/*@-compdestroy@*/
yasm_object *
00092 yasm_object_create(void)
{
    yasm_object *object = yasm_xmalloc(sizeof(yasm_object));

    /* Create empty symtab and linemap */
    object->symtab = yasm_symtab_create();
    object->linemap = yasm_linemap_create();

    /* Initialize sections linked list */
    STAILQ_INIT(&object->sections);

    return object;
}
/*@=compdestroy@*/

/*@-onlytrans@*/
yasm_section *
00109 yasm_object_get_general(yasm_object *object, const char *name,
                  yasm_expr *start, int res_only, int *isnew,
                  unsigned long line)
{
    yasm_section *s;
    yasm_bytecode *bc;

    /* Search through current sections to see if we already have one with
     * that name.
     */
    STAILQ_FOREACH(s, &object->sections, link) {
      if (s->type == SECTION_GENERAL &&
          strcmp(s->data.general.name, name) == 0) {
          *isnew = 0;
          return s;
      }
    }

    /* No: we have to allocate and create a new one. */

    /* Okay, the name is valid; now allocate and initialize */
    s = yasm_xcalloc(1, sizeof(yasm_section));
    STAILQ_INSERT_TAIL(&object->sections, s, link);

    s->object = object;
    s->type = SECTION_GENERAL;
    s->data.general.name = yasm__xstrdup(name);
    s->assoc_data = NULL;
    if (start)
      s->start = start;
    else
      s->start =
          yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)),
                           line);

    /* Initialize bytecodes with one empty bytecode (acts as "prior" for first
     * real bytecode in section.
     */
    STAILQ_INIT(&s->bcs);
    bc = yasm_bc_create_common(NULL, sizeof(yasm_bytecode), 0);
    bc->section = s;
    STAILQ_INSERT_TAIL(&s->bcs, bc, link);

    /* Initialize relocs */
    STAILQ_INIT(&s->relocs);
    s->destroy_reloc = NULL;

    s->res_only = res_only;

    *isnew = 1;
    return s;
}
/*@=onlytrans@*/

/*@-onlytrans@*/
yasm_section *
00165 yasm_object_create_absolute(yasm_object *object, yasm_expr *start,
                      unsigned long line)
{
    yasm_section *s;
    yasm_bytecode *bc;

    s = yasm_xcalloc(1, sizeof(yasm_section));
    STAILQ_INSERT_TAIL(&object->sections, s, link);

    s->object = object;
    s->type = SECTION_ABSOLUTE;
    s->start = start;

    /* Initialize bytecodes with one empty bytecode (acts as "prior" for first
     * real bytecode in section.
     */
    STAILQ_INIT(&s->bcs);
    bc = yasm_bc_create_common(NULL, sizeof(yasm_bytecode), 0);
    bc->section = s;
    STAILQ_INSERT_TAIL(&s->bcs, bc, link);

    /* Initialize relocs */
    STAILQ_INIT(&s->relocs);
    s->destroy_reloc = NULL;

    s->res_only = 1;

    return s;
}
/*@=onlytrans@*/

yasm_symtab *
00197 yasm_object_get_symtab(const yasm_object *object)
{
    return object->symtab;
}

yasm_linemap *
00203 yasm_object_get_linemap(const yasm_object *object)
{
    return object->linemap;
}

int
00209 yasm_section_is_absolute(yasm_section *sect)
{
    return (sect->type == SECTION_ABSOLUTE);
}

unsigned long
00215 yasm_section_get_opt_flags(const yasm_section *sect)
{
    return sect->opt_flags;
}

void
00221 yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags)
{
    sect->opt_flags = opt_flags;
}

yasm_object *
00227 yasm_section_get_object(const yasm_section *sect)
{
    return sect->object;
}

void *
00233 yasm_section_get_data(yasm_section *sect,
                  const yasm_assoc_data_callback *callback)
{
    return yasm__assoc_data_get(sect->assoc_data, callback);
}

void
00240 yasm_section_add_data(yasm_section *sect,
                  const yasm_assoc_data_callback *callback, void *data)
{
    sect->assoc_data = yasm__assoc_data_add(sect->assoc_data, callback, data);
}

void
00247 yasm_object_destroy(yasm_object *object)
{
    yasm_section *cur, *next;

    /* Delete sections */
    cur = STAILQ_FIRST(&object->sections);
    while (cur) {
      next = STAILQ_NEXT(cur, link);
      yasm_section_destroy(cur);
      cur = next;
    }

    /* Delete symbol table and line mappings */
    yasm_symtab_destroy(object->symtab);
    yasm_linemap_destroy(object->linemap);

    yasm_xfree(object);
}

void
00267 yasm_object_print(const yasm_object *object, FILE *f, int indent_level)
{
    yasm_section *cur;

    /* Print symbol table */
    fprintf(f, "%*sSymbol Table:\n", indent_level, "");
    yasm_symtab_print(object->symtab, f, indent_level+1);

    /* Print sections and bytecodes */
    STAILQ_FOREACH(cur, &object->sections, link) {
      fprintf(f, "%*sSection:\n", indent_level, "");
      yasm_section_print(cur, f, indent_level+1, 1);
    }
}

int
00283 yasm_object_sections_traverse(yasm_object *object, /*@null@*/ void *d,
                        int (*func) (yasm_section *sect,
                                 /*@null@*/ void *d))
{
    yasm_section *cur;

    STAILQ_FOREACH(cur, &object->sections, link) {
      int retval = func(cur, d);
      if (retval != 0)
          return retval;
    }
    return 0;
}

/*@-onlytrans@*/
yasm_section *
00299 yasm_object_find_general(yasm_object *object, const char *name)
{
    yasm_section *cur;

    STAILQ_FOREACH(cur, &object->sections, link) {
      if (cur->type == SECTION_GENERAL &&
          strcmp(cur->data.general.name, name) == 0)
          return cur;
    }
    return NULL;
}
/*@=onlytrans@*/

void
00313 yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
                   void (*destroy_func) (/*@only@*/ void *reloc))
{
    STAILQ_INSERT_TAIL(&sect->relocs, reloc, link);
    if (!destroy_func)
      yasm_internal_error(N_("NULL destroy function given to add_reloc"));
    else if (sect->destroy_reloc && destroy_func != sect->destroy_reloc)
      yasm_internal_error(N_("different destroy function given to add_reloc"));
    sect->destroy_reloc = destroy_func;
}

/*@null@*/ yasm_reloc *
00325 yasm_section_relocs_first(yasm_section *sect)
{
    return STAILQ_FIRST(&sect->relocs);
}

#undef yasm_section_reloc_next
/*@null@*/ yasm_reloc *
00332 yasm_section_reloc_next(yasm_reloc *reloc)
{
    return STAILQ_NEXT(reloc, link);
}

void
00338 yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp, yasm_symrec **symp)
{
    *addrp = reloc->addr;
    *symp = reloc->sym;
}


yasm_bytecode *
00346 yasm_section_bcs_first(yasm_section *sect)
{
    return STAILQ_FIRST(&sect->bcs);
}

yasm_bytecode *
00352 yasm_section_bcs_last(yasm_section *sect)
{
    return STAILQ_LAST(&sect->bcs, yasm_bytecode, link);
}

yasm_bytecode *
00358 yasm_section_bcs_append(yasm_section *sect, yasm_bytecode *bc)
{
    if (bc) {
      if (bc->callback) {
          bc->section = sect;     /* record parent section */
          STAILQ_INSERT_TAIL(&sect->bcs, bc, link);
          return bc;
      } else
          yasm_xfree(bc);
    }
    return (yasm_bytecode *)NULL;
}

int
00372 yasm_section_bcs_traverse(yasm_section *sect, void *d,
                    int (*func) (yasm_bytecode *bc, /*@null@*/ void *d))
{
    yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);

    /* Skip our locally created empty bytecode first. */
    cur = STAILQ_NEXT(cur, link);

    /* Iterate through the remainder, if any. */
    while (cur) {
      int retval = func(cur, d);
      if (retval != 0)
          return retval;
      cur = STAILQ_NEXT(cur, link);
    }
    return 0;
}

const char *
00391 yasm_section_get_name(const yasm_section *sect)
{
    if (sect->type == SECTION_GENERAL)
      return sect->data.general.name;
    return NULL;
}

void
00399 yasm_section_set_start(yasm_section *sect, yasm_expr *start,
                   unsigned long line)
{
    yasm_expr_destroy(sect->start);
    sect->start = start;
}

const yasm_expr *
00407 yasm_section_get_start(const yasm_section *sect)
{
    return sect->start;
}

static void
yasm_section_destroy(yasm_section *sect)
{
    yasm_bytecode *cur, *next;
    yasm_reloc *r_cur, *r_next;

    if (!sect)
      return;

    if (sect->type == SECTION_GENERAL) {
      yasm_xfree(sect->data.general.name);
    }
    yasm__assoc_data_destroy(sect->assoc_data);
    yasm_expr_destroy(sect->start);

    /* Delete bytecodes */
    cur = STAILQ_FIRST(&sect->bcs);
    while (cur) {
      next = STAILQ_NEXT(cur, link);
      yasm_bc_destroy(cur);
      cur = next;
    }

    /* Delete relocations */
    r_cur = STAILQ_FIRST(&sect->relocs);
    while (r_cur) {
      r_next = STAILQ_NEXT(r_cur, link);
      yasm_intnum_destroy(r_cur->addr);
      sect->destroy_reloc(r_cur);
      r_cur = r_next;
    }

    yasm_xfree(sect);
}

void
00448 yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
               int print_bcs)
{
    if (!sect) {
      fprintf(f, "%*s(none)\n", indent_level, "");
      return;
    }

    fprintf(f, "%*stype=", indent_level, "");
    switch (sect->type) {
      case SECTION_GENERAL:
          fprintf(f, "general\n%*sname=%s\n", indent_level, "",
                sect->data.general.name);
          break;
      case SECTION_ABSOLUTE:
          fprintf(f, "absolute\n");
          break;
    }

    fprintf(f, "%*sstart=", indent_level, "");
    yasm_expr_print(sect->start, f);
    fprintf(f, "\n");

    if (sect->assoc_data) {
      fprintf(f, "%*sAssociated data:\n", indent_level, "");
      yasm__assoc_data_print(sect->assoc_data, f, indent_level+1);
    }

    if (print_bcs) {
      yasm_bytecode *cur;

      fprintf(f, "%*sBytecodes:\n", indent_level, "");

      STAILQ_FOREACH(cur, &sect->bcs, link) {
          fprintf(f, "%*sNext Bytecode:\n", indent_level+1, "");
          yasm_bc_print(cur, f, indent_level+2);
      }
    }
}

Generated by  Doxygen 1.6.0   Back to index