Ejemplo n.º 1
0
static struct block_symbol
cp_basic_lookup_symbol (const char *name, const struct block *block,
			const domain_enum domain, int is_in_anonymous)
{
  struct block_symbol sym;

  sym = lookup_symbol_in_static_block (name, block, domain);
  if (sym.symbol != NULL)
    return sym;

  if (is_in_anonymous)
    {
      /* Symbols defined in anonymous namespaces have external linkage
	 but should be treated as local to a single file nonetheless.
	 So we only search the current file's global block.  */

      const struct block *global_block = block_global_block (block);

      if (global_block != NULL)
	{
	  sym.symbol = lookup_symbol_in_block (name, global_block, domain);
	  sym.block = global_block;
	}
    }
  else
    sym = lookup_global_symbol (name, block, domain);

  return sym;
}
Ejemplo n.º 2
0
static struct block_symbol
cp_search_static_and_baseclasses (const char *name,
				  const struct block *block,
				  const domain_enum domain,
				  unsigned int prefix_len,
				  int is_in_anonymous)
{
  struct block_symbol sym;
  char *klass, *nested;
  struct cleanup *cleanup;
  struct block_symbol klass_sym;
  struct type *klass_type;

  /* The test here uses <= instead of < because Fortran also uses this,
     and the module.exp testcase will pass "modmany::" for NAME here.  */
  gdb_assert (prefix_len + 2 <= strlen (name));
  gdb_assert (name[prefix_len + 1] == ':');

  /* Find the name of the class and the name of the method, variable, etc.  */

  /* The class name is everything up to and including PREFIX_LEN.  */
  klass = savestring (name, prefix_len);

  /* The rest of the name is everything else past the initial scope
     operator.  */
  nested = xstrdup (name + prefix_len + 2);

  /* Add cleanups to free memory for these strings.  */
  cleanup = make_cleanup (xfree, klass);
  make_cleanup (xfree, nested);

  /* Lookup a class named KLASS.  If none is found, there is nothing
     more that can be done.  KLASS could be a namespace, so always look
     in VAR_DOMAIN.  This works for classes too because of
     symbol_matches_domain (which should be replaced with something else,
     but it's what we have today).  */
  klass_sym = lookup_global_symbol (klass, block, VAR_DOMAIN);
  if (klass_sym.symbol == NULL)
    {
      do_cleanups (cleanup);
      return null_block_symbol;
    }
  klass_type = SYMBOL_TYPE (klass_sym.symbol);

  /* Look for a symbol named NESTED in this class.
     The caller is assumed to have already have done a basic lookup of NAME.
     So we pass zero for BASIC_LOOKUP to cp_lookup_nested_symbol_1 here.  */
  sym = cp_lookup_nested_symbol_1 (klass_type, nested, name, block, domain,
				   0, is_in_anonymous);

  do_cleanups (cleanup);
  return sym;
}
Ejemplo n.º 3
0
/*
 * lookup_exported_symbol_objname - find the object/module an exported
 * symbol belongs to.
 */
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
{
	struct export_symbol *sym, *match = NULL;
	int i;

	for_each_exp_symbol(i, sym, table) {
		if (!strcmp(sym->name, name)) {
			if (match)
				ERROR("duplicate exported symbol found for %s", name);
			match = sym;
		}
	}

	if (match)
		return match->objname;

	return NULL;
 }

#if 0 /* for local testing */
static void find_this(struct lookup_table *table, char *sym, char *hint)
{
	struct lookup_result result;

	if (hint)
		lookup_local_symbol(table, sym, hint, &result);
	else
		lookup_global_symbol(table, sym, &result);

	printf("%s %s w/ %s hint at 0x%016lx len %lu pos %lu\n",
	       hint ? "local" : "global", sym, hint ? hint : "no",
	       result.value, result.size, result.pos);
}
Ejemplo n.º 4
0
static struct block_symbol
cp_lookup_bare_symbol (const struct language_defn *langdef,
		       const char *name, const struct block *block,
		       const domain_enum domain, int search)
{
  struct block_symbol sym;

  /* Note: We can't do a simple assert for ':' not being in NAME because
     ':' may be in the args of a template spec.  This isn't intended to be
     a complete test, just cheap and documentary.  */
  if (strchr (name, '<') == NULL && strchr (name, '(') == NULL)
    gdb_assert (strchr (name, ':') == NULL);

  sym = lookup_symbol_in_static_block (name, block, domain);
  if (sym.symbol != NULL)
    return sym;

  /* If we didn't find a definition for a builtin type in the static block,
     search for it now.  This is actually the right thing to do and can be
     a massive performance win.  E.g., when debugging a program with lots of
     shared libraries we could search all of them only to find out the
     builtin type isn't defined in any of them.  This is common for types
     like "void".  */
  if (langdef != NULL && domain == VAR_DOMAIN)
    {
      struct gdbarch *gdbarch;

      if (block == NULL)
	gdbarch = target_gdbarch ();
      else
	gdbarch = block_gdbarch (block);
      sym.symbol
	= language_lookup_primitive_type_as_symbol (langdef, gdbarch, name);
      sym.block = NULL;
      if (sym.symbol != NULL)
	return sym;
    }

  sym = lookup_global_symbol (name, block, domain);
  if (sym.symbol != NULL)
    return sym;

  if (search)
    {
      struct block_symbol lang_this;
      struct type *type;

      lang_this = lookup_language_this (language_def (language_cplus), block);
      if (lang_this.symbol == NULL)
	return null_block_symbol;

      type = check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (lang_this.symbol)));
      /* If TYPE_NAME is NULL, abandon trying to find this symbol.
	 This can happen for lambda functions compiled with clang++,
	 which outputs no name for the container class.  */
      if (TYPE_NAME (type) == NULL)
	return null_block_symbol;

      /* Look for symbol NAME in this class.  */
      sym = cp_lookup_nested_symbol (type, name, block, domain);
    }

  return sym;
}
Ejemplo n.º 5
0
static struct block_symbol
d_lookup_symbol (const struct language_defn *langdef,
		 const char *name, const struct block *block,
		 const domain_enum domain, int search)
{
  struct block_symbol sym;

  sym = lookup_symbol_in_static_block (name, block, domain);
  if (sym.symbol != NULL)
    return sym;

  /* If we didn't find a definition for a builtin type in the static block,
     such as "ucent" which is a specialist type, search for it now.  */
  if (langdef != NULL && domain == VAR_DOMAIN)
    {
      struct gdbarch *gdbarch;

      if (block == NULL)
	gdbarch = target_gdbarch ();
      else
	gdbarch = block_gdbarch (block);
      sym.symbol
	= language_lookup_primitive_type_as_symbol (langdef, gdbarch, name);
      sym.block = NULL;
      if (sym.symbol != NULL)
	return sym;
    }

  sym = lookup_global_symbol (name, block, domain);

  if (sym.symbol != NULL)
    return sym;

  if (search)
    {
      char *classname, *nested;
      unsigned int prefix_len;
      struct cleanup *cleanup;
      struct block_symbol class_sym;

      /* A simple lookup failed.  Check if the symbol was defined in
	 a base class.  */

      cleanup = make_cleanup (null_cleanup, NULL);

      /* Find the name of the class and the name of the method,
	 variable, etc.  */
      prefix_len = d_entire_prefix_len (name);

      /* If no prefix was found, search "this".  */
      if (prefix_len == 0)
	{
	  struct type *type;
	  struct block_symbol lang_this;

	  lang_this = lookup_language_this (language_def (language_d), block);
	  if (lang_this.symbol == NULL)
	    {
	      do_cleanups (cleanup);
	      return null_block_symbol;
	    }

	  type = check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (lang_this.symbol)));
	  classname = xstrdup (TYPE_NAME (type));
	  nested = xstrdup (name);
	}
      else
	{
	  /* The class name is everything up to and including PREFIX_LEN.  */
	  classname = savestring (name, prefix_len);

	  /* The rest of the name is everything else past the initial scope
	     operator.  */
	  nested = xstrdup (name + prefix_len + 1);
	}

      /* Add cleanups to free memory for these strings.  */
      make_cleanup (xfree, classname);
      make_cleanup (xfree, nested);

      /* Lookup a class named CLASSNAME.  If none is found, there is nothing
	 more that can be done.  */
      class_sym = lookup_global_symbol (classname, block, domain);
      if (class_sym.symbol == NULL)
	{
	  do_cleanups (cleanup);
	  return null_block_symbol;
	}

      /* Look for a symbol named NESTED in this class.  */
      sym = d_lookup_nested_symbol (SYMBOL_TYPE (class_sym.symbol),
				    nested, block);
      do_cleanups (cleanup);
    }

  return sym;
}
Ejemplo n.º 6
0
Archivo: ld.c Proyecto: unixaaa/LuxCC
int main(int argc, char *argv[])
{
    /*
                [ Executable file format ]

    +-------------------------------------------------+ <-+
    | Bss size in bytes (4 bytes)                     |   |
    +-------------------------------------------------+   |
    | Data size in bytes (4 bytes)                    |   |
    +-------------------------------------------------+   |
    | Text size in bytes (4 bytes)                    |   |-> Header
    +-------------------------------------------------+   |
    | Number of entries in data relocation table      |   |
    +-------------------------------------------------+   |
    | Number of entries in text relocation table      |   |
    +-------------------------------------------------+ <-+
    | Data                                            |
    +-------------------------------------------------+
    | Text                                            |
    +-------------------------------------------------+
    | Data relocation table                           |
    +-------------------------------------------------+
    | Text relocation table                           |
    +-------------------------------------------------+


    Each entry of the relocation tables:
        - offset: the offset from the start of the segment (data or text) where the fix
        must be made.
        - segment: indicates if the runtime start address of the bss, data, or text segment
        must be added to do the fix.
    */

    int i;
    FILE *fout;
    char *outpath;
    char *infiles[64];
    int ninf;
    int print_stats;

    prog_name = argv[0];
    if (argc == 1)
        err_no_input();
    ninf = 0;
    print_stats = FALSE;
    outpath = "a.out.vme";
    for (i = 1; i < argc; i++) {
        if (argv[i][0] != '-') {
            infiles[ninf++] = argv[i];
            continue;
        }
        switch (argv[i][1]) {
        case 'o':
            if (argv[i][2] != '\0') {
                outpath = argv[i]+2;
            } else if (argv[i+1] == NULL) {
                fprintf(stderr, "%s: option `o' requires an argument\n", prog_name);
                exit(1);
            } else {
                outpath = argv[++i];
            }
            break;
        case 's':
            print_stats = TRUE;
            break;
        case 'v':
            if (equal(argv[i]+1, "vm64"))
                targeting_vm64 = TRUE;
            else if (equal(argv[i]+1, "vm32"))
                ;
            else
                unk_opt(argv[i]);
            break;
        case 'h':
            printf("usage: %s [ options ] <input-file> ...\n"
                   "  The available options are:\n"
                   "    -o<file>    write output to <file>\n"
                   "    -s          print linking stats\n"
                   "    -vm32       output a 32-bit executable (default)\n"
                   "    -vm64       output a 64-bit executable\n"
                   "    -h          print this help\n", prog_name);
            exit(0);
            break;
        case '\0':
            break;
        default:
            unk_opt(argv[i]);
            break;
        }
    }
    if (ninf == 0)
        err_no_input();

    init_local_table();
    text_max = 65536;
    text_seg = malloc(text_max);
    data_max = 65536;
    data_seg = malloc(data_max);
    dreloc_max = 8192;
    data_relocation_table = malloc(sizeof(Reloc)*dreloc_max);
    treloc_max = 8192;
    text_relocation_table = malloc(sizeof(Reloc)*treloc_max);

    /*
     * crt.o must be the first file (crt.o's code must be physically at the
     * beginning of the resulting executable). An alternative would be to label
     * crt.o's code as, say, `_start:' and emit an "jmp _start;" before the
     * program's code.
     * crt.o has code to initialize some variables and call main.
     */
    for (i = 0; i < ninf; i++) {
        FILE *fin;
        char name[MAX_SYM_LEN], *cp;
        int j;
        int nsym;
        int curr_bss_size;
        int curr_text_size;
        int curr_data_size;
        int curr_nreloc;
        int segment, offset, kind;

        if ((fin=fopen(infiles[i], "rb")) == NULL)
            TERMINATE("%s: error reading file `%s'", prog_name, infiles[i]);

        /* header */
        fread(&nsym, sizeof(int), 1, fin);
        fread(&curr_bss_size, sizeof(int), 1, fin);
        fread(&curr_data_size, sizeof(int), 1, fin);
        fread(&curr_text_size, sizeof(int), 1, fin);
        fread(&curr_nreloc, sizeof(int), 1, fin);

        /* symbol table entries */
        for (j = 0; j < nsym; j++) {
            for (cp = name; ; cp++) {
                if ((*cp=(char)fgetc(fin)) == '\0')
                    break;
            }
            fread(&segment, sizeof(int), 1, fin);
            fread(&offset, sizeof(int), 1, fin);
            fread(&kind, sizeof(int), 1, fin);
            if (kind == LOCAL_SYM)
                define_local_symbol(name, segment, SEG_SIZ(segment)+offset);
            else
                define_symbol(name, kind, segment, SEG_SIZ(segment)+offset);
            // if (segment == TEXT_SEG)
				// printf("%s, %d\n", name, SEG_SIZ(segment)+offset);
        }

        /* data&text */
        if (data_size+curr_data_size > data_max) {
            char *p;

            data_max = data_max*2+curr_data_size;
            if ((p=realloc(data_seg, data_max)) == NULL)
                TERMINATE("out of memory");
            data_seg = p;
        }
        fread(data_seg+data_size, curr_data_size, 1, fin);
        if (text_size+curr_text_size > text_max) {
            char *p;

            text_max = text_max*2+curr_text_size;
            if ((p=realloc(text_seg, text_max)) == NULL)
                TERMINATE("out of memory");
            text_seg = p;
        }
        fread(text_seg+text_size, curr_text_size, 1, fin);

        /* relocation table entries */
        for (j = 0; j < curr_nreloc; j++) {
            Symbol *s;

            fread(&segment, sizeof(int), 1, fin);
            fread(&offset, sizeof(int), 1, fin);
            for (cp = name; ; cp++) {
                if ((*cp=(char)fgetc(fin)) == '\0')
                    break;
            }
            s = lookup_symbol(name);
            if (s->kind != EXTERN_SYM) {
                if (segment == TEXT_SEG) {
                    if (targeting_vm64)
                        *(long long *)&text_seg[SEG_SIZ(segment)+offset] += s->offset;
                    else
                        *(int *)&text_seg[SEG_SIZ(segment)+offset] += s->offset;
                    append_text_reloc(s->segment, SEG_SIZ(segment)+offset, NULL);
                } else {
                    if (targeting_vm64)
                        *(long long *)&data_seg[SEG_SIZ(segment)+offset] += s->offset;
                    else
                        *(int *)&data_seg[SEG_SIZ(segment)+offset] += s->offset;
                    append_data_reloc(s->segment, SEG_SIZ(segment)+offset, NULL);
                }
            } else {
                /*
                 * The file that contains the symbol definition
                 * has not been seen yet. Mark it to fix later.
                 */
                if (segment == TEXT_SEG)
                    append_text_reloc(0, SEG_SIZ(segment)+offset, strdup(name));
                else
                    append_data_reloc(0, SEG_SIZ(segment)+offset, strdup(name));
            }
        }

        if (targeting_vm64) {
            bss_size  += round_up(curr_bss_size,  MAX_ALIGN64);
            data_size += round_up(curr_data_size, MAX_ALIGN64);
            text_size += round_up(curr_text_size, MAX_ALIGN64);
        } else {
            bss_size  += round_up(curr_bss_size,  MAX_ALIGN32);
            data_size += round_up(curr_data_size, MAX_ALIGN32);
            text_size += round_up(curr_text_size, MAX_ALIGN32);
        }
        reset_local_table();
        fclose(fin);
    }

    /*
     * Try to fix the relocs that couldn't be fixed before
     * because they depended on not-yet-defined extern symbols.
     * Fail if a symbol is still undefined.
     */
    for (i = 0; i < ntreloc; i++) {
        if (text_relocation_table[i].symbol != NULL) {
            Symbol *s;

            if ((s=lookup_global_symbol(text_relocation_table[i].symbol))->kind == EXTERN_SYM)
                TERMINATE("%s: undefined reference to `%s'", prog_name, s->name);
            if (targeting_vm64)
                *(long long *)&text_seg[text_relocation_table[i].offset] += s->offset;
            else
                *(int *)&text_seg[text_relocation_table[i].offset] += s->offset;
            text_relocation_table[i].segment = s->segment;
        }
    }
    for (i = 0; i < ndreloc; i++) {
        if (data_relocation_table[i].symbol != NULL) {
            Symbol *s;

            if ((s=lookup_global_symbol(data_relocation_table[i].symbol))->kind == EXTERN_SYM)
                TERMINATE("%s: undefined reference to `%s'", prog_name, s->name);
            if (targeting_vm64)
                *(long long *)&data_seg[data_relocation_table[i].offset] += s->offset;
            else
                *(int *)&data_seg[data_relocation_table[i].offset] += s->offset;
            data_relocation_table[i].segment = s->segment;
        }
    }

    /* Write the final executable file. */
    fout = fopen(outpath, "wb");
    /* header */
    fwrite(&bss_size, sizeof(int), 1, fout);
    fwrite(&data_size, sizeof(int), 1, fout);
    fwrite(&text_size, sizeof(int), 1, fout);
    fwrite(&ndreloc, sizeof(int), 1, fout);
    fwrite(&ntreloc, sizeof(int), 1, fout);
    /* data&text */
    fwrite(data_seg, data_size, 1, fout);
    fwrite(text_seg, text_size, 1, fout);
    /* data relocation table */
    for (i = 0; i < ndreloc; i++) {
        fwrite(&data_relocation_table[i].segment, sizeof(int), 1, fout);
        fwrite(&data_relocation_table[i].offset, sizeof(int), 1, fout);
    }
    /* text relocation table */
    for (i = 0; i < ntreloc; i++) {
        fwrite(&text_relocation_table[i].segment, sizeof(int), 1, fout);
        fwrite(&text_relocation_table[i].offset, sizeof(int), 1, fout);
    }
    fclose(fout);

    if (print_stats) {
        printf("Text size: %d\n", text_size);
        printf("Data size: %d\n", data_size);
        printf("Bss size: %d\n", bss_size);
        printf("Number of text relocations: %d\n", ntreloc);
        printf("Number of data relocations: %d\n", ndreloc);
    }

    free(data_seg);
    free(text_seg);
    free(data_relocation_table);
    free(text_relocation_table);

    return 0;
}