Back to index

cell-binutils  2.17cvs20070401
Functions
budbg.h File Reference
#include <stdio.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void * read_debugging_info (bfd *, asymbol **, long)
bfd_boolean print_debugging_info (FILE *, void *, bfd *, asymbol **, void *, bfd_boolean)
void * start_stab (void *, bfd *, bfd_boolean, asymbol **, long)
bfd_boolean finish_stab (void *, void *)
bfd_boolean parse_stab (void *, void *, int, int, bfd_vma, const char *)
bfd_boolean write_stabs_in_sections_debugging_info (bfd *, void *, bfd_byte **, bfd_size_type *, bfd_byte **, bfd_size_type *)
bfd_boolean parse_ieee (void *, bfd *, const bfd_byte *, bfd_size_type)
bfd_boolean write_ieee_debugging_info (bfd *, void *)
bfd_boolean parse_coff (bfd *, asymbol **, long, void *)

Function Documentation

bfd_boolean finish_stab ( void *  ,
void *   
)

Definition at line 376 of file stabs.c.

{
  struct stab_handle *info = (struct stab_handle *) handle;
  struct stab_tag *st;

  if (info->within_function)
    {
      if (! stab_emit_pending_vars (dhandle, info)
         || ! debug_end_function (dhandle, info->function_end))
       return FALSE;
      info->within_function = FALSE;
      info->function_end = (bfd_vma) -1;
    }

  for (st = info->tags; st != NULL; st = st->next)
    {
      enum debug_type_kind kind;

      kind = st->kind;
      if (kind == DEBUG_KIND_ILLEGAL)
       kind = DEBUG_KIND_STRUCT;
      st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
      if (st->slot == DEBUG_TYPE_NULL)
       return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean parse_coff ( bfd ,
asymbol **  ,
long  ,
void *   
)

Definition at line 653 of file rdcoff.c.

{
  struct coff_symbols symbols;
  struct coff_types types;
  int i;
  long next_c_file;
  const char *fnname;
  int fnclass;
  int fntype;
  bfd_vma fnend;
  alent *linenos;
  bfd_boolean within_function;
  long this_coff_symno;

  symbols.syms = syms;
  symbols.symcount = symcount;
  symbols.symno = 0;
  symbols.coff_symno = 0;

  types.slots = NULL;
  for (i = 0; i <= T_MAX; i++)
    types.basic[i] = DEBUG_TYPE_NULL;

  next_c_file = -1;
  fnname = NULL;
  fnclass = 0;
  fntype = 0;
  fnend = 0;
  linenos = NULL;
  within_function = FALSE;

  while (symbols.symno < symcount)
    {
      asymbol *sym;
      const char *name;
      struct internal_syment syment;
      union internal_auxent auxent;
      union internal_auxent *paux;
      debug_type type;

      sym = syms[symbols.symno];

      if (! bfd_coff_get_syment (abfd, sym, &syment))
       {
         non_fatal (_("bfd_coff_get_syment failed: %s"),
                   bfd_errmsg (bfd_get_error ()));
         return FALSE;
       }

      name = bfd_asymbol_name (sym);

      this_coff_symno = symbols.coff_symno;

      ++symbols.symno;
      symbols.coff_symno += 1 + syment.n_numaux;

      /* We only worry about the first auxent, because that is the
        only one which is relevant for debugging information.  */
      if (syment.n_numaux == 0)
       paux = NULL;
      else
       {
         if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
           {
             non_fatal (_("bfd_coff_get_auxent failed: %s"),
                      bfd_errmsg (bfd_get_error ()));
             return FALSE;
           }
         paux = &auxent;
       }

      if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
       {
         /* The last C_FILE symbol points to the first external
             symbol.  */
         if (! debug_set_filename (dhandle, "*globals*"))
           return FALSE;
       }

      switch (syment.n_sclass)
       {
       case C_EFCN:
       case C_EXTDEF:
       case C_ULABEL:
       case C_USTATIC:
       case C_LINE:
       case C_ALIAS:
       case C_HIDDEN:
         /* Just ignore these classes.  */
         break;

       case C_FILE:
         next_c_file = syment.n_value;
         if (! debug_set_filename (dhandle, name))
           return FALSE;
         break;

       case C_STAT:
         /* Ignore static symbols with a type of T_NULL.  These
             represent section entries.  */
         if (syment.n_type == T_NULL)
           break;
         /* Fall through.  */
       case C_WEAKEXT:
       case C_EXT:
         if (ISFCN (syment.n_type))
           {
             fnname = name;
             fnclass = syment.n_sclass;
             fntype = syment.n_type;
             if (syment.n_numaux > 0)
              fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
             else
              fnend = 0;
             linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
             break;
           }
         type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
                              syment.n_type, paux, TRUE, dhandle);
         if (type == DEBUG_TYPE_NULL)
           return FALSE;
         if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
                               dhandle, type, within_function))
           return FALSE;
         break;

       case C_FCN:
         if (strcmp (name, ".bf") == 0)
           {
             if (fnname == NULL)
              {
                non_fatal (_("%ld: .bf without preceding function"),
                          this_coff_symno);
                return FALSE;
              }

             type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
                                  DECREF (fntype), paux, FALSE, dhandle);
             if (type == DEBUG_TYPE_NULL)
              return FALSE;

             if (! debug_record_function (dhandle, fnname, type,
                                      external_coff_symbol_p (fnclass),
                                      bfd_asymbol_value (sym)))
              return FALSE;

             if (linenos != NULL)
              {
                int base;
                bfd_vma addr;

                if (syment.n_numaux == 0)
                  base = 0;
                else
                  base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;

                addr = bfd_get_section_vma (abfd, bfd_get_section (sym));

                ++linenos;

                while (linenos->line_number != 0)
                  {
                    if (! debug_record_line (dhandle,
                                          linenos->line_number + base,
                                          linenos->u.offset + addr))
                     return FALSE;
                    ++linenos;
                  }
              }

             fnname = NULL;
             linenos = NULL;
             fnclass = 0;
             fntype = 0;

             within_function = TRUE;
           }
         else if (strcmp (name, ".ef") == 0)
           {
             if (! within_function)
              {
                non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno);
                return FALSE;
              }

             if (bfd_asymbol_value (sym) > fnend)
              fnend = bfd_asymbol_value (sym);
             if (! debug_end_function (dhandle, fnend))
              return FALSE;

             fnend = 0;
             within_function = FALSE;
           }
         break;

       case C_BLOCK:
         if (strcmp (name, ".bb") == 0)
           {
             if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
              return FALSE;
           }
         else if (strcmp (name, ".eb") == 0)
           {
             if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
              return FALSE;
           }
         break;

       default:
         type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
                              syment.n_type, paux, TRUE, dhandle);
         if (type == DEBUG_TYPE_NULL)
           return FALSE;
         if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
                               dhandle, type, within_function))
           return FALSE;
         break;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean parse_ieee ( void *  ,
bfd ,
const bfd_byte ,
bfd_size_type   
)

Definition at line 857 of file ieee.c.

{
  struct ieee_info info;
  unsigned int i;
  const bfd_byte *p, *pend;

  info.dhandle = dhandle;
  info.abfd = abfd;
  info.bytes = bytes;
  info.pend = bytes + len;
  info.blockstack.bsp = info.blockstack.stack;
  info.saw_filename = FALSE;
  info.vars.alloc = 0;
  info.vars.vars = NULL;
  info.global_vars = NULL;
  info.types.alloc = 0;
  info.types.types = NULL;
  info.global_types = NULL;
  info.tags = NULL;
  for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
    info.types.builtins[i] = DEBUG_TYPE_NULL;

  p = bytes;
  pend = info.pend;
  while (p < pend)
    {
      const bfd_byte *record_start;
      ieee_record_enum_type c;

      record_start = p;

      c = (ieee_record_enum_type) *p++;

      if (c == ieee_at_record_enum)
       c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);

      if (c <= ieee_number_repeat_end_enum)
       {
         ieee_error (&info, record_start, _("unexpected number"));
         return FALSE;
       }

      switch (c)
       {
       default:
         ieee_error (&info, record_start, _("unexpected record type"));
         return FALSE;

       case ieee_bb_record_enum:
         if (! parse_ieee_bb (&info, &p))
           return FALSE;
         break;

       case ieee_be_record_enum:
         if (! parse_ieee_be (&info, &p))
           return FALSE;
         break;

       case ieee_nn_record:
         if (! parse_ieee_nn (&info, &p))
           return FALSE;
         break;

       case ieee_ty_record_enum:
         if (! parse_ieee_ty (&info, &p))
           return FALSE;
         break;

       case ieee_atn_record_enum:
         if (! parse_ieee_atn (&info, &p))
           return FALSE;
         break;
       }
    }

  if (info.blockstack.bsp != info.blockstack.stack)
    {
      ieee_error (&info, (const bfd_byte *) NULL,
                _("blocks left on stack at end"));
      return FALSE;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean parse_stab ( void *  ,
void *  ,
int  ,
int  ,
bfd_vma  ,
const char *   
)

Definition at line 408 of file stabs.c.

{
  struct stab_handle *info = (struct stab_handle *) handle;

  /* gcc will emit two N_SO strings per compilation unit, one for the
     directory name and one for the file name.  We just collect N_SO
     strings as we see them, and start the new compilation unit when
     we see a non N_SO symbol.  */
  if (info->so_string != NULL
      && (type != N_SO || *string == '\0' || value != info->so_value))
    {
      if (! debug_set_filename (dhandle, info->so_string))
       return FALSE;
      info->main_filename = info->so_string;

      info->gcc_compiled = 0;
      info->n_opt_found = FALSE;

      /* Generally, for stabs in the symbol table, the N_LBRAC and
        N_RBRAC symbols are relative to the N_SO symbol value.  */
      if (! info->sections)
       info->file_start_offset = info->so_value;

      /* We need to reset the mapping from type numbers to types.  We
        can't free the old mapping, because of the use of
        debug_make_indirect_type.  */
      info->files = 1;
      info->file_types = ((struct stab_types **)
                       xmalloc (sizeof *info->file_types));
      info->file_types[0] = NULL;

      info->so_string = NULL;

      /* Now process whatever type we just got.  */
    }

  switch (type)
    {
    case N_FN:
    case N_FN_SEQ:
      break;

    case N_LBRAC:
      /* Ignore extra outermost context from SunPRO cc and acc.  */
      if (info->n_opt_found && desc == 1)
       break;

      if (! info->within_function)
       {
         fprintf (stderr, _("N_LBRAC not within function\n"));
         return FALSE;
       }

      /* Start an inner lexical block.  */
      if (! debug_start_block (dhandle,
                            (value
                            + info->file_start_offset
                            + info->function_start_offset)))
       return FALSE;

      /* Emit any pending variable definitions.  */
      if (! stab_emit_pending_vars (dhandle, info))
       return FALSE;

      ++info->block_depth;
      break;

    case N_RBRAC:
      /* Ignore extra outermost context from SunPRO cc and acc.  */
      if (info->n_opt_found && desc == 1)
       break;

      /* We shouldn't have any pending variable definitions here, but,
         if we do, we probably need to emit them before closing the
         block.  */
      if (! stab_emit_pending_vars (dhandle, info))
       return FALSE;

      /* End an inner lexical block.  */
      if (! debug_end_block (dhandle,
                          (value
                           + info->file_start_offset
                           + info->function_start_offset)))
       return FALSE;

      --info->block_depth;
      if (info->block_depth < 0)
       {
         fprintf (stderr, _("Too many N_RBRACs\n"));
         return FALSE;
       }
      break;

    case N_SO:
      /* This always ends a function.  */
      if (info->within_function)
       {
         bfd_vma endval;

         endval = value;
         if (*string != '\0'
             && info->function_end != (bfd_vma) -1
             && info->function_end < endval)
           endval = info->function_end;
         if (! stab_emit_pending_vars (dhandle, info)
             || ! debug_end_function (dhandle, endval))
           return FALSE;
         info->within_function = FALSE;
         info->function_end = (bfd_vma) -1;
       }

      /* An empty string is emitted by gcc at the end of a compilation
         unit.  */
      if (*string == '\0')
       return TRUE;

      /* Just accumulate strings until we see a non N_SO symbol.  If
         the string starts with a directory separator or some other
        form of absolute path specification, we discard the previously
         accumulated strings.  */
      if (info->so_string == NULL)
       info->so_string = xstrdup (string);
      else
       {
         char *f;

         f = info->so_string;

         if (IS_ABSOLUTE_PATH (string))
           info->so_string = xstrdup (string);
         else
           info->so_string = concat (info->so_string, string,
                                  (const char *) NULL);
         free (f);
       }

      info->so_value = value;

      break;

    case N_SOL:
      /* Start an include file.  */
      if (! debug_start_source (dhandle, string))
       return FALSE;
      break;

    case N_BINCL:
      /* Start an include file which may be replaced.  */
      push_bincl (info, string, value);
      if (! debug_start_source (dhandle, string))
       return FALSE;
      break;

    case N_EINCL:
      /* End an N_BINCL include.  */
      if (! debug_start_source (dhandle, pop_bincl (info)))
       return FALSE;
      break;

    case N_EXCL:
      /* This is a duplicate of a header file named by N_BINCL which
         was eliminated by the linker.  */
      if (! find_excl (info, string, value))
       return FALSE;
      break;

    case N_SLINE:
      if (! debug_record_line (dhandle, desc,
                            value + (info->within_function
                                   ? info->function_start_offset : 0)))
       return FALSE;
      break;

    case N_BCOMM:
      if (! debug_start_common_block (dhandle, string))
       return FALSE;
      break;

    case N_ECOMM:
      if (! debug_end_common_block (dhandle, string))
       return FALSE;
      break;

    case N_FUN:
      if (*string == '\0')
       {
         if (info->within_function)
           {
             /* This always marks the end of a function; we don't
                 need to worry about info->function_end.  */
             if (info->sections)
              value += info->function_start_offset;
             if (! stab_emit_pending_vars (dhandle, info)
                || ! debug_end_function (dhandle, value))
              return FALSE;
             info->within_function = FALSE;
             info->function_end = (bfd_vma) -1;
           }
         break;
       }

      /* A const static symbol in the .text section will have an N_FUN
         entry.  We need to use these to mark the end of the function,
         in case we are looking at gcc output before it was changed to
         always emit an empty N_FUN.  We can't call debug_end_function
         here, because it might be a local static symbol.  */
      if (info->within_function
         && (info->function_end == (bfd_vma) -1
             || value < info->function_end))
       info->function_end = value;

      /* Fall through.  */
      /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
         symbols, and if it does not start with :S, gdb relocates the
         value to the start of the section.  gcc always seems to use
         :S, so we don't worry about this.  */
      /* Fall through.  */
    default:
      {
       const char *colon;

       colon = strchr (string, ':');
       if (colon != NULL
           && (colon[1] == 'f' || colon[1] == 'F'))
         {
           if (info->within_function)
             {
              bfd_vma endval;

              endval = value;
              if (info->function_end != (bfd_vma) -1
                  && info->function_end < endval)
                endval = info->function_end;
              if (! stab_emit_pending_vars (dhandle, info)
                  || ! debug_end_function (dhandle, endval))
                return FALSE;
              info->function_end = (bfd_vma) -1;
             }
           /* For stabs in sections, line numbers and block addresses
               are offsets from the start of the function.  */
           if (info->sections)
             info->function_start_offset = value;
           info->within_function = TRUE;
         }

       if (! parse_stab_string (dhandle, info, type, desc, value, string))
         return FALSE;
      }
      break;

    case N_OPT:
      if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
       info->gcc_compiled = 2;
      else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
       info->gcc_compiled = 1;
      else
       info->n_opt_found = TRUE;
      break;

    case N_OBJ:
    case N_ENDM:
    case N_MAIN:
    case N_WARNING:
      break;
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bfd_boolean print_debugging_info ( FILE *  ,
void *  ,
bfd ,
asymbol **  ,
void *  ,
bfd_boolean   
)

Definition at line 295 of file prdbg.c.

{
  struct pr_handle info;

  info.f = f;
  info.indent = 0;
  info.stack = NULL;
  info.parameter = 0;
  info.filename = NULL;
  info.abfd = abfd;
  info.syms = syms;
  info.demangler = demangler;

  if (as_tags)
    {
      fputs ("!_TAG_FILE_FORMAT\t2\t/extended format/\n", f);
      fputs ("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n", f);
      fputs ("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n", f);
      fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f);
    }

  return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info)
    : debug_write (dhandle, &pr_fns, (void *) & info);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* read_debugging_info ( bfd ,
asymbol **  ,
long   
)

Definition at line 46 of file rddbg.c.

{
  void *dhandle;
  bfd_boolean found;

  dhandle = debug_init ();
  if (dhandle == NULL)
    return NULL;

  if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
                                      &found))
    return NULL;

  if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
    {
      if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
                                         &found))
       return NULL;
    }

  if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour)
    {
      if (! read_ieee_debugging_info (abfd, dhandle, &found))
       return NULL;
    }

  /* Try reading the COFF symbols if we didn't find any stabs in COFF
     sections.  */
  if (! found
      && bfd_get_flavour (abfd) == bfd_target_coff_flavour
      && symcount > 0)
    {
      if (! parse_coff (abfd, syms, symcount, dhandle))
       return NULL;
      found = TRUE;
    }

  if (! found)
    {
      non_fatal (_("%s: no recognized debugging information"),
               bfd_get_filename (abfd));
      return NULL;
    }

  return dhandle;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* start_stab ( void *  ,
bfd ,
bfd_boolean  ,
asymbol **  ,
long   
)

Here is the caller graph for this function:

bfd_boolean write_ieee_debugging_info ( bfd ,
void *   
)

Definition at line 4585 of file ieee.c.

{
  struct ieee_handle info;
  asection *s;
  const char *err;
  struct ieee_buf *b;

  memset (&info, 0, sizeof info);
  info.abfd = abfd;
  info.type_indx = 256;
  info.name_indx = 32;

  if (!bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc,
                         sizeof (struct ieee_name_type_hash_entry))
      || !bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc,
                            sizeof (struct ieee_name_type_hash_entry)))
    return FALSE;

  if (! ieee_init_buffer (&info, &info.global_types)
      || ! ieee_init_buffer (&info, &info.data)
      || ! ieee_init_buffer (&info, &info.types)
      || ! ieee_init_buffer (&info, &info.vars)
      || ! ieee_init_buffer (&info, &info.cxx)
      || ! ieee_init_buffer (&info, &info.linenos)
      || ! ieee_init_buffer (&info, &info.fntype)
      || ! ieee_init_buffer (&info, &info.fnargs))
    return FALSE;

  if (! debug_write (dhandle, &ieee_fns, (void *) &info))
    return FALSE;

  if (info.filename != NULL)
    {
      if (! ieee_finish_compilation_unit (&info))
       return FALSE;
    }

  /* Put any undefined tags in the global typedef information.  */
  info.error = FALSE;
  ieee_name_type_hash_traverse (&info.tags,
                            ieee_write_undefined_tag,
                            (void *) &info);
  if (info.error)
    return FALSE;

  /* Prepend the global typedef information to the other data.  */
  if (! ieee_buffer_emptyp (&info.global_types))
    {
      /* The HP debugger seems to have a bug in which it ignores the
         last entry in the global types, so we add a dummy entry.  */
      if (! ieee_change_buffer (&info, &info.global_types)
         || ! ieee_write_byte (&info, (int) ieee_nn_record)
         || ! ieee_write_number (&info, info.name_indx)
         || ! ieee_write_id (&info, "")
         || ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
         || ! ieee_write_number (&info, info.type_indx)
         || ! ieee_write_byte (&info, 0xce)
         || ! ieee_write_number (&info, info.name_indx)
         || ! ieee_write_number (&info, 'P')
         || ! ieee_write_number (&info, (int) builtin_void + 32)
         || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
       return FALSE;

      if (! ieee_append_buffer (&info, &info.global_types, &info.data))
       return FALSE;
      info.data = info.global_types;
    }

  /* Make sure that we have declare BB11 blocks for each range in the
     file.  They are added to info->vars.  */
  info.error = FALSE;
  if (! ieee_init_buffer (&info, &info.vars))
    return FALSE;
  bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (void *) &info);
  if (info.error)
    return FALSE;
  if (! ieee_buffer_emptyp (&info.vars))
    {
      if (! ieee_change_buffer (&info, &info.vars)
         || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
       return FALSE;

      if (! ieee_append_buffer (&info, &info.data, &info.vars))
       return FALSE;
    }

  /* Now all the data is in info.data.  Write it out to the BFD.  We
     normally would need to worry about whether all the other sections
     are set up yet, but the IEEE backend will handle this particular
     case correctly regardless.  */
  if (ieee_buffer_emptyp (&info.data))
    {
      /* There is no debugging information.  */
      return TRUE;
    }
  err = NULL;
  s = bfd_make_section (abfd, ".debug");
  if (s == NULL)
    err = "bfd_make_section";
  if (err == NULL)
    {
      if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
       err = "bfd_set_section_flags";
    }
  if (err == NULL)
    {
      bfd_size_type size;

      size = 0;
      for (b = info.data.head; b != NULL; b = b->next)
       size += b->c;
      if (! bfd_set_section_size (abfd, s, size))
       err = "bfd_set_section_size";
    }
  if (err == NULL)
    {
      file_ptr offset;

      offset = 0;
      for (b = info.data.head; b != NULL; b = b->next)
       {
         if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
           {
             err = "bfd_set_section_contents";
             break;
           }
         offset += b->c;
       }
    }

  if (err != NULL)
    {
      fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
              bfd_errmsg (bfd_get_error ()));
      return FALSE;
    }

  bfd_hash_table_free (&info.typedefs.root);
  bfd_hash_table_free (&info.tags.root);

  return TRUE;
}

Here is the call graph for this function:

Definition at line 462 of file wrstabs.c.

{
  struct stab_write_handle info;
  struct string_hash_entry *h;
  bfd_byte *p;

  info.abfd = abfd;

  info.symbols_size = 0;
  info.symbols_alloc = 500;
  info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc);

  info.strings = NULL;
  info.last_string = NULL;
  /* Reserve 1 byte for a null byte.  */
  info.strings_size = 1;

  if (!bfd_hash_table_init (&info.strhash.table, string_hash_newfunc,
                         sizeof (struct string_hash_entry))
      || !bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc,
                            sizeof (struct string_hash_entry)))
    {
      non_fatal ("bfd_hash_table_init_failed: %s",
               bfd_errmsg (bfd_get_error ()));
      return FALSE;
    }

  info.type_stack = NULL;
  info.type_index = 1;
  memset (&info.type_cache, 0, sizeof info.type_cache);
  info.so_offset = -1;
  info.fun_offset = -1;
  info.last_text_address = 0;
  info.nesting = 0;
  info.fnaddr = 0;
  info.pending_lbrac = (bfd_vma) -1;

  /* The initial symbol holds the string size.  */
  if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL))
    return FALSE;

  /* Output an initial N_SO symbol.  */
  info.so_offset = info.symbols_size;
  if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd)))
    return FALSE;

  if (! debug_write (dhandle, &stab_fns, (void *) &info))
    return FALSE;

  assert (info.pending_lbrac == (bfd_vma) -1);

  /* Output a trailing N_SO.  */
  if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address,
                        (const char *) NULL))
    return FALSE;

  /* Put the string size in the initial symbol.  */
  bfd_put_32 (abfd, info.strings_size, info.symbols + 8);

  *psyms = info.symbols;
  *psymsize = info.symbols_size;

  *pstringsize = info.strings_size;
  *pstrings = (bfd_byte *) xmalloc (info.strings_size);

  p = *pstrings;
  *p++ = '\0';
  for (h = info.strings; h != NULL; h = h->next)
    {
      strcpy ((char *) p, h->root.string);
      p += strlen ((char *) p) + 1;
    }

  return TRUE;
}

Here is the call graph for this function: