#include "as.h"
#include "ecoff.h"
#ifdef ECOFF_DEBUGGING
#include "coff/internal.h"
#include "coff/symconst.h"
#include "aout/stab_gnu.h"
#include "safe-ctype.h"
#define ST_RFDESCAPE 0xfff
typedef enum sc {
sc_Nil = scNil,
sc_Text = scText,
sc_Data = scData,
sc_Bss = scBss,
sc_Register = scRegister,
sc_Abs = scAbs,
sc_Undefined = scUndefined,
sc_CdbLocal = scCdbLocal,
sc_Bits = scBits,
sc_CdbSystem = scCdbSystem,
sc_RegImage = scRegImage,
sc_Info = scInfo,
sc_UserStruct = scUserStruct,
sc_SData = scSData,
sc_SBss = scSBss,
sc_RData = scRData,
sc_Var = scVar,
sc_Common = scCommon,
sc_SCommon = scSCommon,
sc_VarRegister = scVarRegister,
sc_Variant = scVariant,
sc_SUndefined = scSUndefined,
sc_Init = scInit,
sc_Max = scMax
} sc_t;
typedef enum st {
st_Nil = stNil,
st_Global = stGlobal,
st_Static = stStatic,
st_Param = stParam,
st_Local = stLocal,
st_Label = stLabel,
st_Proc = stProc,
st_Block = stBlock,
st_End = stEnd,
st_Member = stMember,
st_Typedef = stTypedef,
st_File = stFile,
st_RegReloc = stRegReloc,
st_Forward = stForward,
st_StaticProc = stStaticProc,
st_Constant = stConstant,
st_Str = stStr,
st_Number = stNumber,
st_Expr = stExpr,
st_Type = stType,
st_Max = stMax
} st_t;
typedef enum tq {
tq_Nil = tqNil,
tq_Ptr = tqPtr,
tq_Proc = tqProc,
tq_Array = tqArray,
tq_Far = tqFar,
tq_Vol = tqVol,
tq_Max = tqMax
} tq_t;
typedef enum bt {
bt_Nil = btNil,
bt_Adr = btAdr,
bt_Char = btChar,
bt_UChar = btUChar,
bt_Short = btShort,
bt_UShort = btUShort,
bt_Int = btInt,
bt_UInt = btUInt,
bt_Long = btLong,
bt_ULong = btULong,
bt_Float = btFloat,
bt_Double = btDouble,
bt_Struct = btStruct,
bt_Union = btUnion,
bt_Enum = btEnum,
bt_Typedef = btTypedef,
bt_Range = btRange,
bt_Set = btSet,
bt_Complex = btComplex,
bt_DComplex = btDComplex,
bt_Indirect = btIndirect,
bt_FixedDec = btFixedDec,
bt_FloatDec = btFloatDec,
bt_String = btString,
bt_Bit = btBit,
bt_Picture = btPicture,
bt_Void = btVoid,
bt_Max = btMax
} bt_t;
#define N_TQ itqMax
typedef enum hash_state {
hash_no = 0,
hash_yes = 1,
hash_record = 2
} hash_state_t;
enum alloc_type {
alloc_type_none,
alloc_type_scope,
alloc_type_vlinks,
alloc_type_shash,
alloc_type_thash,
alloc_type_tag,
alloc_type_forward,
alloc_type_thead,
alloc_type_varray,
alloc_type_lineno,
alloc_type_last
};
enum aux_type {
aux_tir,
aux_rndx,
aux_dnLow,
aux_dnHigh,
aux_isym,
aux_iss,
aux_width,
aux_count
};
#ifndef PAGE_SIZE
#define PAGE_SIZE (8*1024)
#endif
#define PAGE_USIZE ((unsigned long) PAGE_SIZE)
#ifndef MAX_CLUSTER_PAGES
#define MAX_CLUSTER_PAGES 63
#endif
typedef struct vlinks {
struct vlinks *prev;
struct vlinks *next;
union page *datum;
unsigned long start_index;
} vlinks_t;
typedef struct varray {
vlinks_t *first;
vlinks_t *last;
unsigned long num_allocated;
unsigned short object_size;
unsigned short objects_per_page;
unsigned short objects_last_page;
} varray_t;
#ifndef MALLOC_CHECK
#define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
#else
#define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
#endif
#define INIT_VARRAY(type) { \
(vlinks_t *)0, \
(vlinks_t *)0, \
0, \
sizeof (type), \
OBJECTS_PER_PAGE (type), \
OBJECTS_PER_PAGE (type), \
}
typedef unsigned long symint_t;
typedef struct scope {
struct scope *prev;
struct scope *free;
struct localsym *lsym;
st_t type;
} scope_t;
typedef struct localsym {
const char *name;
symbolS *as_sym;
bfd_vma addend;
struct efdr *file_ptr;
struct ecoff_proc *proc_ptr;
struct localsym *begin_ptr;
struct ecoff_aux *index_ptr;
struct forward *forward_ref;
long sym_index;
EXTR ecoff_sym;
} localsym_t;
typedef struct ecoff_aux {
enum aux_type type;
AUXU data;
} aux_t;
typedef struct ecoff_proc {
localsym_t *sym;
PDR pdr;
} proc_t;
static unsigned long proc_cnt;
typedef struct forward {
struct forward *next;
struct forward *free;
aux_t *ifd_ptr;
aux_t *index_ptr;
} forward_t;
typedef struct tag {
struct tag *free;
struct shash *hash_ptr;
struct tag *same_name;
struct tag *same_block;
struct forward *forward_ref;
bt_t basic_type;
symint_t ifd;
localsym_t *sym;
} tag_t;
typedef struct thead {
struct thead *prev;
struct thead *free;
struct tag *first_tag;
} thead_t;
typedef union small_free {
scope_t *f_scope;
thead_t *f_thead;
tag_t *f_tag;
forward_t *f_forward;
} small_free_t;
typedef struct shash {
char *string;
symint_t indx;
EXTR *esym_ptr;
localsym_t *sym_ptr;
localsym_t *end_ptr;
tag_t *tag_ptr;
proc_t *proc_ptr;
} shash_t;
#define HASHBITS 30
#ifndef THASH_SIZE
#define THASH_SIZE 113
#endif
typedef struct thash {
struct thash *next;
AUXU type;
symint_t indx;
} thash_t;
typedef struct efdr {
FDR fdr;
FDR *orig_fdr;
char *name;
int fake;
symint_t void_type;
symint_t int_type;
scope_t *cur_scope;
symint_t file_index;
int nested_scopes;
varray_t strings;
varray_t symbols;
varray_t procs;
varray_t aux_syms;
struct efdr *next_file;
struct hash_control *str_hash;
thash_t *thash_head[THASH_SIZE];
} efdr_t;
static const efdr_t init_file = {
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
langC,
1,
0,
TARGET_BYTES_BIG_ENDIAN,
GLEVEL_2,
0,
0,
0,
},
(FDR *)0,
(char *)0,
0,
0,
0,
(scope_t *)0,
0,
0,
INIT_VARRAY (char),
INIT_VARRAY (localsym_t),
INIT_VARRAY (proc_t),
INIT_VARRAY (aux_t),
(struct efdr *)0,
(struct hash_control *)0,
{ 0 },
};
static efdr_t *first_file;
static efdr_t **last_file_ptr = &first_file;
typedef struct lineno_list {
struct lineno_list *next;
efdr_t *file;
proc_t *proc;
fragS *frag;
unsigned long paddr;
long lineno;
} lineno_list_t;
static lineno_list_t *first_lineno;
static lineno_list_t *last_lineno;
static lineno_list_t **last_lineno_ptr = &first_lineno;
static lineno_list_t *noproc_lineno;
typedef union page {
char byte [ PAGE_SIZE ];
unsigned char ubyte [ PAGE_SIZE ];
efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ];
FDR ofile [ PAGE_SIZE / sizeof (FDR) ];
proc_t proc [ PAGE_SIZE / sizeof (proc_t) ];
localsym_t sym [ PAGE_SIZE / sizeof (localsym_t) ];
aux_t aux [ PAGE_SIZE / sizeof (aux_t) ];
DNR dense [ PAGE_SIZE / sizeof (DNR) ];
scope_t scope [ PAGE_SIZE / sizeof (scope_t) ];
vlinks_t vlinks [ PAGE_SIZE / sizeof (vlinks_t) ];
shash_t shash [ PAGE_SIZE / sizeof (shash_t) ];
thash_t thash [ PAGE_SIZE / sizeof (thash_t) ];
tag_t tag [ PAGE_SIZE / sizeof (tag_t) ];
forward_t forward [ PAGE_SIZE / sizeof (forward_t) ];
thead_t thead [ PAGE_SIZE / sizeof (thead_t) ];
lineno_list_t lineno [ PAGE_SIZE / sizeof (lineno_list_t) ];
} page_type;
typedef struct alloc_info {
char *alloc_name;
page_type *cur_page;
small_free_t free_list;
int unallocated;
int total_alloc;
int total_free;
int total_pages;
} alloc_info_t;
typedef struct type_info {
bt_t basic_type;
int orig_type;
int num_tq;
int num_dims;
int num_sizes;
int extra_sizes;
tag_t * tag_ptr;
int bitfield;
tq_t type_qualifiers[N_TQ];
symint_t dimensions [N_TQ];
symint_t sizes [N_TQ+2];
} type_info_t;
static const type_info_t type_info_init = {
bt_Nil,
T_NULL,
0,
0,
0,
0,
NULL,
0,
{
tq_Nil,
tq_Nil,
tq_Nil,
tq_Nil,
tq_Nil,
tq_Nil,
},
{
0,
0,
0,
0,
0,
0
},
{
0,
0,
0,
0,
0,
0,
0,
0,
},
};
static varray_t file_desc = INIT_VARRAY (efdr_t);
static struct hash_control *tag_hash;
static type_info_t int_type_info;
static type_info_t void_type_info;
static type_info_t last_func_type_info;
static symbolS *last_func_sym_value;
static const bt_t map_coff_types[] = {
bt_Nil,
bt_Nil,
bt_Char,
bt_Short,
bt_Int,
bt_Long,
bt_Float,
bt_Double,
bt_Struct,
bt_Union,
bt_Enum,
bt_Enum,
bt_UChar,
bt_UShort,
bt_UInt,
bt_ULong
};
static const sc_t map_coff_storage[] = {
sc_Nil,
sc_Abs,
sc_Undefined,
sc_Data,
sc_Register,
sc_Undefined,
sc_Text,
sc_Text,
sc_Info,
sc_Abs,
sc_Info,
sc_Info,
sc_Info,
sc_Info,
sc_Data,
sc_Info,
sc_Info,
sc_Register,
sc_Bits,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Text,
sc_Text,
sc_Info,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
};
static const st_t map_coff_sym_type[] = {
st_Nil,
st_Local,
st_Global,
st_Static,
st_Local,
st_Global,
st_Label,
st_Label,
st_Member,
st_Param,
st_Block,
st_Member,
st_Block,
st_Typedef,
st_Static,
st_Block,
st_Member,
st_Param,
st_Member,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Block,
st_Proc,
st_End,
st_File,
st_Nil,
st_Nil,
st_Nil,
};
static alloc_info_t alloc_counts[(int) alloc_type_last];
int ecoff_debugging_seen = 0;
static efdr_t *cur_file_ptr = (efdr_t *) 0;
static proc_t *cur_proc_ptr = (proc_t *) 0;
static proc_t *first_proc_ptr = (proc_t *) 0;
static thead_t *top_tag_head = (thead_t *) 0;
static thead_t *cur_tag_head = (thead_t *) 0;
#ifdef ECOFF_DEBUG
static int debug = 0;
#endif
static int stabs_seen = 0;
static int current_file_idx;
static const char *current_stabs_filename;
#ifndef STABS_SYMBOL
#define STABS_SYMBOL "@stabs"
#endif
static char stabs_symbol[] = STABS_SYMBOL;
static void add_varray_page (varray_t *vp);
static symint_t add_string (varray_t *vp,
struct hash_control *hash_tbl,
const char *str,
shash_t **ret_hash);
static localsym_t *add_ecoff_symbol (const char *str, st_t type,
sc_t storage, symbolS *sym,
bfd_vma addend, symint_t value,
symint_t indx);
static symint_t add_aux_sym_symint (symint_t aux_word);
static symint_t add_aux_sym_rndx (int file_index, symint_t sym_index);
static symint_t add_aux_sym_tir (type_info_t *t,
hash_state_t state,
thash_t **hash_tbl);
static tag_t *get_tag (const char *tag, localsym_t *sym, bt_t basic_type);
static void add_unknown_tag (tag_t *ptag);
static void add_procedure (char *func);
static void add_file (const char *file_name, int indx, int fake);
#ifdef ECOFF_DEBUG
static char *sc_to_string (sc_t storage_class);
static char *st_to_string (st_t symbol_type);
#endif
static void mark_stabs (int);
static char *ecoff_add_bytes (char **buf, char **bufend,
char *bufptr, unsigned long need);
static unsigned long ecoff_padding_adjust
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset, char **bufptrptr);
static unsigned long ecoff_build_lineno
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset, long *linecntptr);
static unsigned long ecoff_build_symbols
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset);
static unsigned long ecoff_build_procs
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset);
static unsigned long ecoff_build_aux
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset);
static unsigned long ecoff_build_strings (char **buf, char **bufend,
unsigned long offset,
varray_t *vp);
static unsigned long ecoff_build_ss
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset);
static unsigned long ecoff_build_fdr
(const struct ecoff_debug_swap *backend, char **buf, char **bufend,
unsigned long offset);
static void ecoff_setup_ext (void);
static page_type *allocate_cluster (unsigned long npages);
static page_type *allocate_page (void);
static scope_t *allocate_scope (void);
static void free_scope (scope_t *ptr);
static vlinks_t *allocate_vlinks (void);
static shash_t *allocate_shash (void);
static thash_t *allocate_thash (void);
static tag_t *allocate_tag (void);
static void free_tag (tag_t *ptr);
static forward_t *allocate_forward (void);
static thead_t *allocate_thead (void);
static void free_thead (thead_t *ptr);
static lineno_list_t *allocate_lineno_list (void);
void
ecoff_read_begin_hook (void)
{
tag_hash = hash_new ();
top_tag_head = allocate_thead ();
top_tag_head->first_tag = (tag_t *) NULL;
top_tag_head->free = (thead_t *) NULL;
top_tag_head->prev = cur_tag_head;
cur_tag_head = top_tag_head;
}
void
ecoff_symbol_new_hook (symbolS *symbolP)
{
OBJ_SYMFIELD_TYPE *obj;
if (cur_file_ptr == (efdr_t *) NULL
&& seen_at_least_1_file ())
add_file ((const char *) NULL, 0, 1);
obj = symbol_get_obj (symbolP);
obj->ecoff_file = cur_file_ptr;
obj->ecoff_symbol = NULL;
obj->ecoff_extern_size = 0;
}
static void
add_varray_page (varray_t *vp )
{
vlinks_t *new_links = allocate_vlinks ();
#ifdef MALLOC_CHECK
if (vp->object_size > 1)
new_links->datum = (page_type *) xcalloc (1, vp->object_size);
else
#endif
new_links->datum = allocate_page ();
alloc_counts[(int) alloc_type_varray].total_alloc++;
alloc_counts[(int) alloc_type_varray].total_pages++;
new_links->start_index = vp->num_allocated;
vp->objects_last_page = 0;
if (vp->first == (vlinks_t *) NULL)
vp->first = vp->last = new_links;
else
{
new_links->prev = vp->last;
vp->last->next = new_links;
vp->last = new_links;
}
}
static symint_t
add_string (varray_t *vp,
struct hash_control *hash_tbl,
const char *str,
shash_t **ret_hash )
{
register unsigned long len = strlen (str);
register shash_t *hash_ptr;
if (len >= PAGE_USIZE)
as_fatal (_("string too big (%lu bytes)"), len);
hash_ptr = (shash_t *) hash_find (hash_tbl, str);
if (hash_ptr == (shash_t *) NULL)
{
register const char *err;
if (vp->objects_last_page + len >= PAGE_USIZE)
{
vp->num_allocated =
((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
add_varray_page (vp);
}
hash_ptr = allocate_shash ();
hash_ptr->indx = vp->num_allocated;
hash_ptr->string = &vp->last->datum->byte[vp->objects_last_page];
vp->objects_last_page += len + 1;
vp->num_allocated += len + 1;
strcpy (hash_ptr->string, str);
err = hash_insert (hash_tbl, str, (char *) hash_ptr);
if (err)
as_fatal (_("inserting \"%s\" into string hash table: %s"),
str, err);
}
if (ret_hash != (shash_t **) NULL)
*ret_hash = hash_ptr;
return hash_ptr->indx;
}
static localsym_t *
add_ecoff_symbol (const char *str,
st_t type,
sc_t storage,
symbolS *sym_value,
bfd_vma addend,
symint_t value,
symint_t indx )
{
localsym_t *psym;
register scope_t *pscope;
register thead_t *ptag_head;
register tag_t *ptag;
register tag_t *ptag_next;
register varray_t *vp;
register int scope_delta = 0;
shash_t *hash_ptr = (shash_t *) NULL;
if (cur_file_ptr == (efdr_t *) NULL)
as_fatal (_("no current file pointer"));
vp = &cur_file_ptr->symbols;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
psym = &vp->last->datum->sym[vp->objects_last_page++];
if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
psym->name = S_GET_NAME (sym_value);
else
psym->name = str;
psym->as_sym = sym_value;
if (sym_value != (symbolS *) NULL)
symbol_get_obj (sym_value)->ecoff_symbol = psym;
psym->addend = addend;
psym->file_ptr = cur_file_ptr;
psym->proc_ptr = cur_proc_ptr;
psym->begin_ptr = (localsym_t *) NULL;
psym->index_ptr = (aux_t *) NULL;
psym->forward_ref = (forward_t *) NULL;
psym->sym_index = -1;
memset (&psym->ecoff_sym, 0, sizeof (EXTR));
psym->ecoff_sym.asym.value = value;
psym->ecoff_sym.asym.st = (unsigned) type;
psym->ecoff_sym.asym.sc = (unsigned) storage;
psym->ecoff_sym.asym.index = indx;
if (sym_value == (symbolS *) NULL)
psym->ecoff_sym.asym.iss = ((str == (const char *) NULL)
? 0
: add_string (&cur_file_ptr->strings,
cur_file_ptr->str_hash,
str,
&hash_ptr));
++vp->num_allocated;
if (ECOFF_IS_STAB (&psym->ecoff_sym.asym))
return psym;
if (hash_ptr != (shash_t *) NULL
&& (type == st_Global || type == st_Static || type == st_Label
|| type == st_Proc || type == st_StaticProc))
hash_ptr->sym_ptr = psym;
switch (type)
{
default:
break;
case st_File:
case st_Proc:
case st_StaticProc:
case st_Block:
pscope = allocate_scope ();
pscope->prev = cur_file_ptr->cur_scope;
pscope->lsym = psym;
pscope->type = type;
cur_file_ptr->cur_scope = pscope;
if (type != st_File)
scope_delta = 1;
if (type != st_File && storage != sc_Info)
{
ptag_head = allocate_thead ();
ptag_head->first_tag = 0;
ptag_head->prev = cur_tag_head;
cur_tag_head = ptag_head;
}
break;
case st_End:
pscope = cur_file_ptr->cur_scope;
if (pscope == (scope_t *) NULL)
as_fatal (_("too many st_End's"));
else
{
st_t begin_type = (st_t) pscope->lsym->ecoff_sym.asym.st;
psym->begin_ptr = pscope->lsym;
if (begin_type != st_File)
scope_delta = -1;
if (begin_type != st_File && storage != sc_Info)
{
ptag_head = cur_tag_head;
cur_tag_head = ptag_head->prev;
for (ptag = ptag_head->first_tag;
ptag != (tag_t *) NULL;
ptag = ptag_next)
{
if (ptag->forward_ref != (forward_t *) NULL)
add_unknown_tag (ptag);
ptag_next = ptag->same_block;
ptag->hash_ptr->tag_ptr = ptag->same_name;
free_tag (ptag);
}
free_thead (ptag_head);
}
cur_file_ptr->cur_scope = pscope->prev;
if (begin_type != st_File && begin_type != st_Block)
{
symint_t ty;
varray_t *svp = &cur_file_ptr->aux_syms;
pscope->lsym->ecoff_sym.asym.index = add_aux_sym_symint (0);
pscope->lsym->index_ptr =
&svp->last->datum->aux[svp->objects_last_page - 1];
ty = add_aux_sym_tir (&last_func_type_info,
hash_no,
&cur_file_ptr->thash_head[0]);
}
free_scope (pscope);
}
}
cur_file_ptr->nested_scopes += scope_delta;
#ifdef ECOFF_DEBUG
if (debug && type != st_File
&& (debug > 2 || type == st_Block || type == st_End
|| type == st_Proc || type == st_StaticProc))
{
char *sc_str = sc_to_string (storage);
char *st_str = st_to_string (type);
int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
fprintf (stderr,
"\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
value, depth, sc_str);
if (str_start && str_end_p1 - str_start > 0)
fprintf (stderr, " st= %-11s name= %.*s\n",
st_str, str_end_p1 - str_start, str_start);
else
{
unsigned long len = strlen (st_str);
fprintf (stderr, " st= %.*s\n", len - 1, st_str);
}
}
#endif
return psym;
}
static symint_t
add_aux_sym_symint (symint_t aux_word )
{
register varray_t *vp;
register aux_t *aux_ptr;
if (cur_file_ptr == (efdr_t *) NULL)
as_fatal (_("no current file pointer"));
vp = &cur_file_ptr->aux_syms;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
aux_ptr->type = aux_isym;
aux_ptr->data.isym = aux_word;
return vp->num_allocated++;
}
static symint_t
add_aux_sym_rndx (int file_index, symint_t sym_index)
{
register varray_t *vp;
register aux_t *aux_ptr;
if (cur_file_ptr == (efdr_t *) NULL)
as_fatal (_("no current file pointer"));
vp = &cur_file_ptr->aux_syms;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
aux_ptr->type = aux_rndx;
aux_ptr->data.rndx.rfd = file_index;
aux_ptr->data.rndx.index = sym_index;
return vp->num_allocated++;
}
static symint_t
add_aux_sym_tir (type_info_t *t,
hash_state_t state,
thash_t **hash_tbl )
{
register varray_t *vp;
register aux_t *aux_ptr;
static AUXU init_aux;
symint_t ret;
int i;
AUXU aux;
if (cur_file_ptr == (efdr_t *) NULL)
as_fatal (_("no current file pointer"));
vp = &cur_file_ptr->aux_syms;
aux = init_aux;
aux.ti.bt = (int) t->basic_type;
aux.ti.continued = 0;
aux.ti.fBitfield = t->bitfield;
aux.ti.tq0 = (int) t->type_qualifiers[0];
aux.ti.tq1 = (int) t->type_qualifiers[1];
aux.ti.tq2 = (int) t->type_qualifiers[2];
aux.ti.tq3 = (int) t->type_qualifiers[3];
aux.ti.tq4 = (int) t->type_qualifiers[4];
aux.ti.tq5 = (int) t->type_qualifiers[5];
if (state != hash_no
&& (t->type_qualifiers[0] == tq_Array
|| t->type_qualifiers[1] == tq_Array
|| t->type_qualifiers[2] == tq_Array
|| t->type_qualifiers[3] == tq_Array
|| t->type_qualifiers[4] == tq_Array
|| t->type_qualifiers[5] == tq_Array
|| t->basic_type == bt_Struct
|| t->basic_type == bt_Union
|| t->basic_type == bt_Enum
|| t->bitfield
|| t->num_dims > 0))
state = hash_no;
if (state != hash_no)
{
register thash_t *hash_ptr;
register symint_t hi;
hi = aux.isym & ((1 << HASHBITS) - 1);
hi %= THASH_SIZE;
for (hash_ptr = hash_tbl[hi];
hash_ptr != (thash_t *)0;
hash_ptr = hash_ptr->next)
{
if (aux.isym == hash_ptr->type.isym)
break;
}
if (hash_ptr != (thash_t *) NULL && state == hash_yes)
return hash_ptr->indx;
if (hash_ptr == (thash_t *) NULL)
{
hash_ptr = allocate_thash ();
hash_ptr->next = hash_tbl[hi];
hash_ptr->type = aux;
hash_ptr->indx = vp->num_allocated;
hash_tbl[hi] = hash_ptr;
}
}
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
aux_ptr->type = aux_tir;
aux_ptr->data = aux;
ret = vp->num_allocated++;
if (t->bitfield)
(void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes - 1]);
if (t->basic_type == bt_Struct
|| t->basic_type == bt_Union
|| t->basic_type == bt_Enum)
{
register symint_t file_index = t->tag_ptr->ifd;
register localsym_t *sym = t->tag_ptr->sym;
register forward_t *forward_ref = allocate_forward ();
if (sym != (localsym_t *) NULL)
{
forward_ref->next = sym->forward_ref;
sym->forward_ref = forward_ref;
}
else
{
forward_ref->next = t->tag_ptr->forward_ref;
t->tag_ptr->forward_ref = forward_ref;
}
(void) add_aux_sym_rndx (ST_RFDESCAPE, indexNil);
forward_ref->index_ptr
= &vp->last->datum->aux[vp->objects_last_page - 1];
(void) add_aux_sym_symint (file_index);
forward_ref->ifd_ptr
= &vp->last->datum->aux[vp->objects_last_page - 1];
}
for (i = 0; i < t->num_dims; i++)
{
(void) add_aux_sym_rndx (ST_RFDESCAPE,
cur_file_ptr->int_type);
(void) add_aux_sym_symint (cur_file_ptr->file_index);
(void) add_aux_sym_symint ((symint_t) 0);
(void) add_aux_sym_symint (t->dimensions[i] - 1);
(void) add_aux_sym_symint ((t->dimensions[i] == 0)
? 0
: (t->sizes[i] * 8) / t->dimensions[i]);
};
return ret;
}
static tag_t *
get_tag (const char *tag,
localsym_t *sym,
bt_t basic_type )
{
shash_t *hash_ptr;
const char *err;
tag_t *tag_ptr;
if (cur_file_ptr == (efdr_t *) NULL)
as_fatal (_("no current file pointer"));
hash_ptr = (shash_t *) hash_find (tag_hash, tag);
if (hash_ptr != (shash_t *) NULL
&& hash_ptr->tag_ptr != (tag_t *) NULL)
{
tag_ptr = hash_ptr->tag_ptr;
if (sym != (localsym_t *) NULL)
{
tag_ptr->basic_type = basic_type;
tag_ptr->ifd = cur_file_ptr->file_index;
tag_ptr->sym = sym;
}
return tag_ptr;
}
if (hash_ptr == (shash_t *) NULL)
{
char *perm;
perm = xstrdup (tag);
hash_ptr = allocate_shash ();
err = hash_insert (tag_hash, perm, (char *) hash_ptr);
if (err)
as_fatal (_("inserting \"%s\" into tag hash table: %s"),
tag, err);
hash_ptr->string = perm;
}
tag_ptr = allocate_tag ();
tag_ptr->forward_ref = (forward_t *) NULL;
tag_ptr->hash_ptr = hash_ptr;
tag_ptr->same_name = hash_ptr->tag_ptr;
tag_ptr->basic_type = basic_type;
tag_ptr->sym = sym;
tag_ptr->ifd = ((sym == (localsym_t *) NULL)
? (symint_t) -1
: cur_file_ptr->file_index);
tag_ptr->same_block = cur_tag_head->first_tag;
cur_tag_head->first_tag = tag_ptr;
hash_ptr->tag_ptr = tag_ptr;
return tag_ptr;
}
static void
add_unknown_tag (tag_t *ptag )
{
shash_t *hash_ptr = ptag->hash_ptr;
char *name = hash_ptr->string;
localsym_t *sym;
forward_t **pf;
#ifdef ECOFF_DEBUG
if (debug > 1)
{
char *agg_type = "{unknown aggregate type}";
switch (ptag->basic_type)
{
case bt_Struct: agg_type = "struct"; break;
case bt_Union: agg_type = "union"; break;
case bt_Enum: agg_type = "enum"; break;
default: break;
}
fprintf (stderr, "unknown %s %.*s found\n", agg_type,
hash_ptr->len, name_start);
}
#endif
sym = add_ecoff_symbol (name,
st_Block,
sc_Info,
(symbolS *) NULL,
(bfd_vma) 0,
(symint_t) 0,
(symint_t) 0);
(void) add_ecoff_symbol (name,
st_End,
sc_Info,
(symbolS *) NULL,
(bfd_vma) 0,
(symint_t) 0,
(symint_t) 0);
for (pf = &sym->forward_ref; *pf != (forward_t *) NULL; pf = &(*pf)->next)
;
*pf = ptag->forward_ref;
}
static void
add_procedure (char *func )
{
register varray_t *vp;
register proc_t *new_proc_ptr;
symbolS *sym;
#ifdef ECOFF_DEBUG
if (debug)
fputc ('\n', stderr);
#endif
if (cur_file_ptr == (efdr_t *) NULL)
as_fatal (_("no current file pointer"));
vp = &cur_file_ptr->procs;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[vp->objects_last_page++];
if (first_proc_ptr == (proc_t *) NULL)
first_proc_ptr = new_proc_ptr;
vp->num_allocated++;
new_proc_ptr->pdr.isym = -1;
new_proc_ptr->pdr.iline = -1;
new_proc_ptr->pdr.lnLow = -1;
new_proc_ptr->pdr.lnHigh = -1;
sym = symbol_find_or_make (func);
symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
sym, (bfd_vma) 0, (symint_t) 0,
(symint_t) 0);
++proc_cnt;
if (noproc_lineno != (lineno_list_t *) NULL)
{
lineno_list_t *l;
for (l = noproc_lineno; l != (lineno_list_t *) NULL; l = l->next)
l->proc = new_proc_ptr;
*last_lineno_ptr = noproc_lineno;
while (*last_lineno_ptr != NULL)
{
last_lineno = *last_lineno_ptr;
last_lineno_ptr = &last_lineno->next;
}
noproc_lineno = (lineno_list_t *) NULL;
}
}
symbolS *
ecoff_get_cur_proc_sym (void)
{
return (cur_proc_ptr ? cur_proc_ptr->sym->as_sym : NULL);
}
static void
add_file (const char *file_name, int indx ATTRIBUTE_UNUSED, int fake)
{
register int first_ch;
register efdr_t *fil_ptr;
#ifdef ECOFF_DEBUG
if (debug)
fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
#endif
if (file_name == (const char *) NULL)
{
char *file;
if (first_file != (efdr_t *) NULL)
as_fatal (_("fake .file after real one"));
as_where (&file, (unsigned int *) NULL);
file_name = (const char *) file;
if (! symbol_table_frozen && debug_type == DEBUG_UNSPECIFIED)
debug_type = DEBUG_ECOFF;
}
else if (debug_type == DEBUG_UNSPECIFIED)
debug_type = DEBUG_NONE;
#ifndef NO_LISTING
if (listing)
listing_source_file (file_name);
#endif
current_stabs_filename = file_name;
if (stabs_seen)
{
(void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
symbol_new ("L0\001", now_seg,
(valueT) frag_now_fix (),
frag_now),
(bfd_vma) 0, 0, ECOFF_MARK_STAB (N_SOL));
return;
}
first_ch = *file_name;
for (fil_ptr = first_file;
fil_ptr != (efdr_t *) NULL;
fil_ptr = fil_ptr->next_file)
{
if (first_ch == fil_ptr->name[0]
&& strcmp (file_name, fil_ptr->name) == 0
&& fil_ptr->fdr.fMerge)
{
cur_file_ptr = fil_ptr;
if (! fake)
cur_file_ptr->fake = 0;
break;
}
}
if (fil_ptr == (efdr_t *) NULL)
{
if (file_desc.objects_last_page == file_desc.objects_per_page)
add_varray_page (&file_desc);
fil_ptr = cur_file_ptr =
&file_desc.last->datum->file[file_desc.objects_last_page++];
*fil_ptr = init_file;
fil_ptr->file_index = current_file_idx++;
++file_desc.num_allocated;
fil_ptr->fake = fake;
fil_ptr->str_hash = hash_new ();
add_string (&fil_ptr->strings,
fil_ptr->str_hash,
"",
(shash_t **)0);
if (strlen (file_name) > PAGE_USIZE - 2)
as_fatal (_("filename goes over one page boundary"));
(void) add_ecoff_symbol (file_name, st_File, sc_Text,
(symbolS *) NULL, (bfd_vma) 0,
(symint_t) 0, (symint_t) 0);
fil_ptr->fdr.rss = 1;
fil_ptr->name = &fil_ptr->strings.last->datum->byte[1];
*last_file_ptr = fil_ptr;
last_file_ptr = &fil_ptr->next_file;
fil_ptr->void_type = add_aux_sym_tir (&void_type_info,
hash_yes,
&cur_file_ptr->thash_head[0]);
fil_ptr->int_type = add_aux_sym_tir (&int_type_info,
hash_yes,
&cur_file_ptr->thash_head[0]);
}
}
void
ecoff_new_file (const char *name)
{
if (cur_file_ptr != NULL && strcmp (cur_file_ptr->name, name) == 0)
return;
add_file (name, 0, 0);
if (debug_type == DEBUG_UNSPECIFIED)
debug_type = DEBUG_ECOFF;
}
#ifdef ECOFF_DEBUG
static char *
sc_to_string (storage_class)
sc_t storage_class;
{
switch (storage_class)
{
case sc_Nil: return "Nil,";
case sc_Text: return "Text,";
case sc_Data: return "Data,";
case sc_Bss: return "Bss,";
case sc_Register: return "Register,";
case sc_Abs: return "Abs,";
case sc_Undefined: return "Undefined,";
case sc_CdbLocal: return "CdbLocal,";
case sc_Bits: return "Bits,";
case sc_CdbSystem: return "CdbSystem,";
case sc_RegImage: return "RegImage,";
case sc_Info: return "Info,";
case sc_UserStruct: return "UserStruct,";
case sc_SData: return "SData,";
case sc_SBss: return "SBss,";
case sc_RData: return "RData,";
case sc_Var: return "Var,";
case sc_Common: return "Common,";
case sc_SCommon: return "SCommon,";
case sc_VarRegister: return "VarRegister,";
case sc_Variant: return "Variant,";
case sc_SUndefined: return "SUndefined,";
case sc_Init: return "Init,";
case sc_Max: return "Max,";
}
return "???,";
}
#endif
#ifdef ECOFF_DEBUG
static char *
st_to_string (symbol_type)
st_t symbol_type;
{
switch (symbol_type)
{
case st_Nil: return "Nil,";
case st_Global: return "Global,";
case st_Static: return "Static,";
case st_Param: return "Param,";
case st_Local: return "Local,";
case st_Label: return "Label,";
case st_Proc: return "Proc,";
case st_Block: return "Block,";
case st_End: return "End,";
case st_Member: return "Member,";
case st_Typedef: return "Typedef,";
case st_File: return "File,";
case st_RegReloc: return "RegReloc,";
case st_Forward: return "Forward,";
case st_StaticProc: return "StaticProc,";
case st_Constant: return "Constant,";
case st_Str: return "String,";
case st_Number: return "Number,";
case st_Expr: return "Expr,";
case st_Type: return "Type,";
case st_Max: return "Max,";
}
return "???,";
}
#endif
void
ecoff_directive_begin (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char name_end;
if (cur_file_ptr == (efdr_t *) NULL)
{
as_warn (_(".begin directive without a preceding .file directive"));
demand_empty_rest_of_line ();
return;
}
if (cur_proc_ptr == (proc_t *) NULL)
{
as_warn (_(".begin directive without a preceding .ent directive"));
demand_empty_rest_of_line ();
return;
}
name = input_line_pointer;
name_end = get_symbol_end ();
(void) add_ecoff_symbol ((const char *) NULL, st_Block, sc_Text,
symbol_find_or_make (name),
(bfd_vma) 0, (symint_t) 0, (symint_t) 0);
*input_line_pointer = name_end;
(void) get_absolute_expression ();
demand_empty_rest_of_line ();
}
void
ecoff_directive_bend (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char name_end;
symbolS *endsym;
if (cur_file_ptr == (efdr_t *) NULL)
{
as_warn (_(".bend directive without a preceding .file directive"));
demand_empty_rest_of_line ();
return;
}
if (cur_proc_ptr == (proc_t *) NULL)
{
as_warn (_(".bend directive without a preceding .ent directive"));
demand_empty_rest_of_line ();
return;
}
name = input_line_pointer;
name_end = get_symbol_end ();
endsym = symbol_find (name);
if (endsym == (symbolS *) NULL)
as_warn (_(".bend directive names unknown symbol"));
else
(void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
(bfd_vma) 0, (symint_t) 0, (symint_t) 0);
*input_line_pointer = name_end;
(void) get_absolute_expression ();
demand_empty_rest_of_line ();
}
static char *coff_sym_name;
static type_info_t coff_type;
static sc_t coff_storage_class;
static st_t coff_symbol_typ;
static int coff_is_function;
static char *coff_tag;
static valueT coff_value;
static symbolS *coff_sym_value;
static bfd_vma coff_sym_addend;
static int coff_inside_enumeration;
void
ecoff_directive_def (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char name_end;
ecoff_debugging_seen = 1;
SKIP_WHITESPACE ();
name = input_line_pointer;
name_end = get_symbol_end ();
if (coff_sym_name != (char *) NULL)
as_warn (_(".def pseudo-op used inside of .def/.endef; ignored"));
else if (*name == '\0')
as_warn (_("empty symbol name in .def; ignored"));
else
{
if (coff_sym_name != (char *) NULL)
free (coff_sym_name);
if (coff_tag != (char *) NULL)
free (coff_tag);
coff_sym_name = xstrdup (name);
coff_type = type_info_init;
coff_storage_class = sc_Nil;
coff_symbol_typ = st_Nil;
coff_is_function = 0;
coff_tag = (char *) NULL;
coff_value = 0;
coff_sym_value = (symbolS *) NULL;
coff_sym_addend = 0;
}
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
}
void
ecoff_directive_dim (int ignore ATTRIBUTE_UNUSED)
{
int dimens[N_TQ];
int i;
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".dim pseudo-op used outside of .def/.endef; ignored"));
demand_empty_rest_of_line ();
return;
}
for (i = 0; i < N_TQ; i++)
{
SKIP_WHITESPACE ();
dimens[i] = get_absolute_expression ();
if (*input_line_pointer == ',')
++input_line_pointer;
else
{
if (*input_line_pointer != '\n'
&& *input_line_pointer != ';')
as_warn (_("badly formed .dim directive"));
break;
}
}
if (i == N_TQ)
--i;
for (; i >= 0; i--)
{
if (coff_type.num_dims >= N_TQ)
{
as_warn (_("too many .dim entries"));
break;
}
coff_type.dimensions[coff_type.num_dims] = dimens[i];
++coff_type.num_dims;
}
demand_empty_rest_of_line ();
}
void
ecoff_directive_scl (int ignore ATTRIBUTE_UNUSED)
{
long val;
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".scl pseudo-op used outside of .def/.endef; ignored"));
demand_empty_rest_of_line ();
return;
}
val = get_absolute_expression ();
coff_symbol_typ = map_coff_sym_type[val];
coff_storage_class = map_coff_storage[val];
demand_empty_rest_of_line ();
}
void
ecoff_directive_size (int ignore ATTRIBUTE_UNUSED)
{
int sizes[N_TQ];
int i;
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".size pseudo-op used outside of .def/.endef; ignored"));
demand_empty_rest_of_line ();
return;
}
for (i = 0; i < N_TQ; i++)
{
SKIP_WHITESPACE ();
sizes[i] = get_absolute_expression ();
if (*input_line_pointer == ',')
++input_line_pointer;
else
{
if (*input_line_pointer != '\n'
&& *input_line_pointer != ';')
as_warn (_("badly formed .size directive"));
break;
}
}
if (i == N_TQ)
--i;
for (; i >= 0; i--)
{
if (coff_type.num_sizes >= N_TQ)
{
as_warn (_("too many .size entries"));
break;
}
coff_type.sizes[coff_type.num_sizes] = sizes[i];
++coff_type.num_sizes;
}
demand_empty_rest_of_line ();
}
void
ecoff_directive_type (int ignore ATTRIBUTE_UNUSED)
{
long val;
tq_t *tq_ptr;
tq_t *tq_shft;
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".type pseudo-op used outside of .def/.endef; ignored"));
demand_empty_rest_of_line ();
return;
}
val = get_absolute_expression ();
coff_type.orig_type = BTYPE (val);
coff_type.basic_type = map_coff_types[coff_type.orig_type];
tq_ptr = &coff_type.type_qualifiers[N_TQ];
while (val & ~N_BTMASK)
{
if (tq_ptr == &coff_type.type_qualifiers[0])
{
as_warn (_("the type of %s is too complex; it will be simplified"),
coff_sym_name);
break;
}
if (ISPTR (val))
*--tq_ptr = tq_Ptr;
else if (ISFCN (val))
*--tq_ptr = tq_Proc;
else if (ISARY (val))
*--tq_ptr = tq_Array;
else
as_fatal (_("Unrecognized .type argument"));
val = DECREF (val);
}
tq_shft = &coff_type.type_qualifiers[0];
while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
*tq_shft++ = *tq_ptr++;
if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
{
coff_is_function = 1;
tq_shft[-1] = tq_Nil;
}
while (tq_shft != &coff_type.type_qualifiers[N_TQ])
*tq_shft++ = tq_Nil;
demand_empty_rest_of_line ();
}
void
ecoff_directive_tag (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char name_end;
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".tag pseudo-op used outside of .def/.endef; ignored"));
demand_empty_rest_of_line ();
return;
}
name = input_line_pointer;
name_end = get_symbol_end ();
coff_tag = xstrdup (name);
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
}
void
ecoff_directive_val (int ignore ATTRIBUTE_UNUSED)
{
expressionS exp;
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".val pseudo-op used outside of .def/.endef; ignored"));
demand_empty_rest_of_line ();
return;
}
expression (&exp);
if (exp.X_op != O_constant && exp.X_op != O_symbol)
{
as_bad (_(".val expression is too copmlex"));
demand_empty_rest_of_line ();
return;
}
if (exp.X_op == O_constant)
coff_value = exp.X_add_number;
else
{
coff_sym_value = exp.X_add_symbol;
coff_sym_addend = exp.X_add_number;
}
demand_empty_rest_of_line ();
}
void
ecoff_directive_endef (int ignore ATTRIBUTE_UNUSED)
{
char *name;
symint_t indx;
localsym_t *sym;
demand_empty_rest_of_line ();
if (coff_sym_name == (char *) NULL)
{
as_warn (_(".endef pseudo-op used before .def; ignored"));
return;
}
name = coff_sym_name;
coff_sym_name = (char *) NULL;
if (coff_sym_value != (symbolS *) NULL)
{
coff_symbol_typ = st_Nil;
coff_storage_class = sc_Nil;
}
coff_type.extra_sizes = coff_tag != (char *) NULL;
if (coff_type.num_dims > 0)
{
int diff = coff_type.num_dims - coff_type.num_sizes;
int i = coff_type.num_dims - 1;
int j;
if (coff_type.num_sizes != 1 || diff < 0)
{
as_warn (_("bad COFF debugging information"));
return;
}
coff_type.extra_sizes = 0;
if (diff)
{
j = (sizeof (coff_type.sizes) / sizeof (coff_type.sizes[0])) - 1;
while (j >= 0)
{
coff_type.sizes[j] = (((j - diff) >= 0)
? coff_type.sizes[j - diff]
: 0);
j--;
}
coff_type.num_sizes = i + 1;
for (i--; i >= 0; i--)
coff_type.sizes[i] = (coff_type.dimensions[i + 1] == 0
? 0
: (coff_type.sizes[i + 1]
/ coff_type.dimensions[i + 1]));
}
}
else if (coff_symbol_typ == st_Member
&& coff_type.num_sizes - coff_type.extra_sizes == 1)
{
coff_type.bitfield = 1;
}
if (coff_symbol_typ == st_Block || coff_symbol_typ == st_End)
indx = 0;
else if (coff_inside_enumeration)
indx = cur_file_ptr->void_type;
else
{
if (coff_type.basic_type == bt_Struct
|| coff_type.basic_type == bt_Union
|| coff_type.basic_type == bt_Enum)
{
if (coff_tag == (char *) NULL)
{
as_warn (_("no tag specified for %s"), name);
return;
}
coff_type.tag_ptr = get_tag (coff_tag, (localsym_t *) NULL,
coff_type.basic_type);
}
if (coff_is_function)
{
last_func_type_info = coff_type;
last_func_sym_value = coff_sym_value;
return;
}
indx = add_aux_sym_tir (&coff_type,
hash_yes,
&cur_file_ptr->thash_head[0]);
}
switch (coff_symbol_typ)
{
default:
break;
case st_Block:
if (coff_type.num_sizes - coff_type.num_dims - coff_type.extra_sizes
!= 1)
{
as_warn (_("bad COFF debugging information"));
return;
}
else
coff_value = coff_type.sizes[0];
coff_inside_enumeration = (coff_type.orig_type == T_ENUM);
break;
case st_End:
free (name);
name = (char *) NULL;
coff_value = 0;
coff_inside_enumeration = 0;
break;
case st_Member:
if (! coff_type.bitfield && ! coff_inside_enumeration)
coff_value *= 8;
break;
}
sym = add_ecoff_symbol (name,
coff_symbol_typ,
coff_storage_class,
coff_sym_value,
coff_sym_addend,
(symint_t) coff_value,
indx);
if (coff_symbol_typ == st_Block)
{
tag_t *tag_ptr = get_tag (name,
sym,
coff_type.basic_type);
forward_t **pf;
for (pf = &sym->forward_ref;
*pf != (forward_t *) NULL;
pf = &(*pf)->next)
;
*pf = tag_ptr->forward_ref;
tag_ptr->forward_ref = (forward_t *) NULL;
}
}
void
ecoff_directive_end (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char name_end;
symbolS *ent;
if (cur_file_ptr == (efdr_t *) NULL)
{
as_warn (_(".end directive without a preceding .file directive"));
demand_empty_rest_of_line ();
return;
}
if (cur_proc_ptr == (proc_t *) NULL)
{
as_warn (_(".end directive without a preceding .ent directive"));
demand_empty_rest_of_line ();
return;
}
name = input_line_pointer;
name_end = get_symbol_end ();
if (name == input_line_pointer)
{
as_warn (_(".end directive has no name"));
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
return;
}
ent = symbol_find (name);
if (ent == (symbolS *) NULL)
as_warn (_(".end directive names unknown symbol"));
else
(void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
symbol_new ("L0\001", now_seg,
(valueT) frag_now_fix (),
frag_now),
(bfd_vma) 0, (symint_t) 0, (symint_t) 0);
cur_proc_ptr = (proc_t *) NULL;
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
}
void
ecoff_directive_ent (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char name_end;
if (cur_file_ptr == (efdr_t *) NULL)
add_file ((const char *) NULL, 0, 1);
if (cur_proc_ptr != (proc_t *) NULL)
{
as_warn (_("second .ent directive found before .end directive"));
demand_empty_rest_of_line ();
return;
}
name = input_line_pointer;
name_end = get_symbol_end ();
if (name == input_line_pointer)
{
as_warn (_(".ent directive has no name"));
*input_line_pointer = name_end;
demand_empty_rest_of_line ();
return;
}
add_procedure (name);
*input_line_pointer = name_end;
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{
++input_line_pointer;
SKIP_WHITESPACE ();
}
if (ISDIGIT (*input_line_pointer)
|| *input_line_pointer == '-')
(void) get_absolute_expression ();
demand_empty_rest_of_line ();
}
void
ecoff_directive_extern (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int c;
symbolS *symbolp;
valueT size;
name = input_line_pointer;
c = get_symbol_end ();
symbolp = symbol_find_or_make (name);
*input_line_pointer = c;
S_SET_EXTERNAL (symbolp);
if (*input_line_pointer == ',')
++input_line_pointer;
size = get_absolute_expression ();
symbol_get_obj (symbolp)->ecoff_extern_size = size;
}
void
ecoff_directive_file (int ignore ATTRIBUTE_UNUSED)
{
int indx;
char *name;
int len;
if (cur_proc_ptr != (proc_t *) NULL)
{
as_warn (_("no way to handle .file within .ent/.end section"));
demand_empty_rest_of_line ();
return;
}
indx = (int) get_absolute_expression ();
name = demand_copy_C_string (&len);
add_file (name, indx - 1, 0);
demand_empty_rest_of_line ();
}
void
ecoff_directive_fmask (int ignore ATTRIBUTE_UNUSED)
{
long val;
if (cur_proc_ptr == (proc_t *) NULL)
{
as_warn (_(".fmask outside of .ent"));
demand_empty_rest_of_line ();
return;
}
if (get_absolute_expression_and_terminator (&val) != ',')
{
as_warn (_("bad .fmask directive"));
--input_line_pointer;
demand_empty_rest_of_line ();
return;
}
cur_proc_ptr->pdr.fregmask = val;
cur_proc_ptr->pdr.fregoffset = get_absolute_expression ();
demand_empty_rest_of_line ();
}
void
ecoff_directive_frame (int ignore ATTRIBUTE_UNUSED)
{
long val;
if (cur_proc_ptr == (proc_t *) NULL)
{
as_warn (_(".frame outside of .ent"));
demand_empty_rest_of_line ();
return;
}
cur_proc_ptr->pdr.framereg = tc_get_register (1);
SKIP_WHITESPACE ();
if (*input_line_pointer++ != ','
|| get_absolute_expression_and_terminator (&val) != ',')
{
as_warn (_("bad .frame directive"));
--input_line_pointer;
demand_empty_rest_of_line ();
return;
}
cur_proc_ptr->pdr.frameoffset = val;
cur_proc_ptr->pdr.pcreg = tc_get_register (0);
#if 0
demand_empty_rest_of_line ();
#else
s_ignore (42);
#endif
}
void
ecoff_directive_mask (int ignore ATTRIBUTE_UNUSED)
{
long val;
if (cur_proc_ptr == (proc_t *) NULL)
{
as_warn (_(".mask outside of .ent"));
demand_empty_rest_of_line ();
return;
}
if (get_absolute_expression_and_terminator (&val) != ',')
{
as_warn (_("bad .mask directive"));
--input_line_pointer;
demand_empty_rest_of_line ();
return;
}
cur_proc_ptr->pdr.regmask = val;
cur_proc_ptr->pdr.regoffset = get_absolute_expression ();
demand_empty_rest_of_line ();
}
void
ecoff_directive_loc (int ignore ATTRIBUTE_UNUSED)
{
lineno_list_t *list;
symint_t lineno;
if (cur_file_ptr == (efdr_t *) NULL)
{
as_warn (_(".loc before .file"));
demand_empty_rest_of_line ();
return;
}
if (now_seg != text_section)
{
as_warn (_(".loc outside of .text"));
demand_empty_rest_of_line ();
return;
}
SKIP_WHITESPACE ();
get_absolute_expression ();
SKIP_WHITESPACE ();
lineno = get_absolute_expression ();
#ifndef NO_LISTING
if (listing)
listing_source_line (lineno);
#endif
if (stabs_seen)
{
(void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
symbol_new ("L0\001", now_seg,
(valueT) frag_now_fix (),
frag_now),
(bfd_vma) 0, 0, lineno);
return;
}
list = allocate_lineno_list ();
list->next = (lineno_list_t *) NULL;
list->file = cur_file_ptr;
list->proc = cur_proc_ptr;
list->frag = frag_now;
list->paddr = frag_now_fix ();
list->lineno = lineno;
cur_file_ptr->fdr.fMerge = 0;
if (cur_proc_ptr == (proc_t *) NULL)
{
lineno_list_t **pl;
pl = &noproc_lineno;
while (*pl != (lineno_list_t *) NULL)
pl = &(*pl)->next;
*pl = list;
}
else
{
last_lineno = list;
*last_lineno_ptr = list;
last_lineno_ptr = &list->next;
}
}
void
ecoff_fix_loc (fragS *old_frag, unsigned long old_frag_offset)
{
if (last_lineno != NULL
&& last_lineno->frag == old_frag
&& last_lineno->paddr == old_frag_offset)
{
last_lineno->frag = frag_now;
last_lineno->paddr = frag_now_fix ();
}
}
static void
mark_stabs (int ignore ATTRIBUTE_UNUSED)
{
if (! stabs_seen)
{
stabs_seen = 1;
(void) add_ecoff_symbol (stabs_symbol, stNil, scInfo,
(symbolS *) NULL,
(bfd_vma) 0, (symint_t) -1,
ECOFF_MARK_STAB (0));
}
}
#ifndef TC_MIPS
void
ecoff_directive_weakext (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int c;
symbolS *symbolP;
expressionS exp;
name = input_line_pointer;
c = get_symbol_end ();
symbolP = symbol_find_or_make (name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{
if (S_IS_DEFINED (symbolP))
{
as_bad (_("symbol `%s' is already defined"),
S_GET_NAME (symbolP));
ignore_rest_of_line ();
return;
}
++input_line_pointer;
SKIP_WHITESPACE ();
if (! is_end_of_line[(unsigned char) *input_line_pointer])
{
expression (&exp);
if (exp.X_op != O_symbol)
{
as_bad (_("bad .weakext directive"));
ignore_rest_of_line ();
return;
}
symbol_set_value_expression (symbolP, &exp);
}
}
S_SET_WEAK (symbolP);
demand_empty_rest_of_line ();
}
#endif
void
ecoff_stab (segT sec ATTRIBUTE_UNUSED,
int what,
const char *string,
int type,
int other,
int desc)
{
efdr_t *save_file_ptr = cur_file_ptr;
symbolS *sym;
symint_t value;
bfd_vma addend;
st_t st;
sc_t sc;
symint_t indx;
localsym_t *hold = NULL;
ecoff_debugging_seen = 1;
if (what != 's' && what != 'n')
{
as_bad (_(".stab%c is not supported"), what);
return;
}
if (what == 'n')
string = NULL;
if (other != 0)
as_warn (_(".stab%c: ignoring non-zero other field"), what);
if (cur_file_ptr == (efdr_t *) NULL)
{
add_file ((const char *) NULL, 0, 1);
save_file_ptr = cur_file_ptr;
}
if (stabs_seen == 0)
mark_stabs (0);
if (type == N_SLINE)
{
SYMR dummy_symr;
char *name;
char name_end;
#ifndef NO_LISTING
if (listing)
listing_source_line ((unsigned int) desc);
#endif
dummy_symr.index = desc;
if (dummy_symr.index != desc)
{
as_warn (_("line number (%d) for .stab%c directive cannot fit in index field (20 bits)"),
desc, what);
return;
}
name = input_line_pointer;
name_end = get_symbol_end ();
sym = symbol_find_or_make (name);
*input_line_pointer = name_end;
value = 0;
addend = 0;
st = st_Label;
sc = sc_Text;
indx = desc;
}
else
{
#ifndef NO_LISTING
if (listing && (type == N_SO || type == N_SOL))
listing_source_file (string);
#endif
if (ISDIGIT (*input_line_pointer)
|| *input_line_pointer == '-'
|| *input_line_pointer == '+')
{
st = st_Nil;
sc = sc_Nil;
sym = (symbolS *) NULL;
value = get_absolute_expression ();
addend = 0;
}
else if (! is_name_beginner ((unsigned char) *input_line_pointer))
{
as_warn (_("illegal .stab%c directive, bad character"), what);
return;
}
else
{
expressionS exp;
sc = sc_Nil;
st = st_Nil;
expression (&exp);
if (exp.X_op == O_constant)
{
sym = NULL;
value = exp.X_add_number;
addend = 0;
}
else if (exp.X_op == O_symbol)
{
sym = exp.X_add_symbol;
value = 0;
addend = exp.X_add_number;
}
else
{
sym = make_expr_symbol (&exp);
value = 0;
addend = 0;
}
}
indx = ECOFF_MARK_STAB (type);
}
if (sym != (symbolS *) NULL)
hold = symbol_get_obj (sym)->ecoff_symbol;
(void) add_ecoff_symbol (string, st, sc, sym, addend, value, indx);
if (sym != (symbolS *) NULL)
symbol_get_obj (sym)->ecoff_symbol = hold;
cur_file_ptr = save_file_ptr;
}
void
ecoff_frob_symbol (symbolS *sym)
{
if (S_IS_COMMON (sym)
&& S_GET_VALUE (sym) > 0
&& S_GET_VALUE (sym) <= bfd_get_gp_size (stdoutput))
{
static asection scom_section;
static asymbol scom_symbol;
if (scom_section.name == NULL)
{
scom_section = bfd_com_section;
scom_section.name = ".scommon";
scom_section.output_section = &scom_section;
scom_section.symbol = &scom_symbol;
scom_section.symbol_ptr_ptr = &scom_section.symbol;
scom_symbol = *bfd_com_section.symbol;
scom_symbol.name = ".scommon";
scom_symbol.section = &scom_section;
}
S_SET_SEGMENT (sym, &scom_section);
}
if (S_IS_WEAK (sym))
{
if (S_IS_COMMON (sym))
as_bad (_("symbol `%s' can not be both weak and common"),
S_GET_NAME (sym));
}
}
static char *
ecoff_add_bytes (char **buf,
char **bufend,
char *bufptr,
unsigned long need)
{
unsigned long at;
unsigned long want;
at = bufptr - *buf;
need -= *bufend - bufptr;
if (need < PAGE_SIZE)
need = PAGE_SIZE;
want = (*bufend - *buf) + need;
*buf = xrealloc (*buf, want);
*bufend = *buf + want;
return *buf + at;
}
static unsigned long
ecoff_padding_adjust (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset,
char **bufptrptr)
{
bfd_size_type align;
align = backend->debug_align;
if ((offset & (align - 1)) != 0)
{
unsigned long add;
add = align - (offset & (align - 1));
if ((unsigned long) (*bufend - (*buf + offset)) < add)
(void) ecoff_add_bytes (buf, bufend, *buf + offset, add);
memset (*buf + offset, 0, add);
offset += add;
if (bufptrptr != (char **) NULL)
*bufptrptr = *buf + offset;
}
return offset;
}
static unsigned long
ecoff_build_lineno (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset,
long *linecntptr)
{
char *bufptr;
register lineno_list_t *l;
lineno_list_t *last;
efdr_t *file;
proc_t *proc;
unsigned long c;
long iline;
long totcount;
lineno_list_t first;
lineno_list_t *local_first_lineno = first_lineno;
if (linecntptr != (long *) NULL)
*linecntptr = 0;
bufptr = *buf + offset;
file = (efdr_t *) NULL;
proc = (proc_t *) NULL;
last = (lineno_list_t *) NULL;
c = offset;
iline = 0;
totcount = 0;
if (debug_type != DEBUG_ECOFF
&& first_proc_ptr != (proc_t *) NULL
&& local_first_lineno != (lineno_list_t *) NULL
&& ((S_GET_VALUE (first_proc_ptr->sym->as_sym)
+ bfd_get_section_vma (stdoutput,
S_GET_SEGMENT (first_proc_ptr->sym->as_sym)))
!= 0))
{
first.file = local_first_lineno->file;
first.proc = local_first_lineno->proc;
first.frag = &zero_address_frag;
first.paddr = 0;
first.lineno = 0;
first.next = local_first_lineno;
local_first_lineno = &first;
}
for (l = local_first_lineno; l != (lineno_list_t *) NULL; l = l->next)
{
long count;
long delta;
if (l->next == (lineno_list_t *) NULL)
{
count = 1;
}
else if (l->next->frag->fr_address + l->next->paddr
> l->frag->fr_address + l->paddr)
{
count = ((l->next->frag->fr_address + l->next->paddr
- (l->frag->fr_address + l->paddr))
>> 2);
}
else
{
continue;
}
if (l->file != file || l->proc != proc)
{
if (l->proc != proc && proc != (proc_t *) NULL)
proc->pdr.lnHigh = last->lineno;
if (l->file != file && file != (efdr_t *) NULL)
{
file->fdr.cbLine = c - file->fdr.cbLineOffset;
file->fdr.cline = totcount + count;
if (linecntptr != (long *) NULL)
*linecntptr += totcount + count;
totcount = 0;
}
if (l->file != file)
{
efdr_t *last_file = file;
file = l->file;
if (last_file != (efdr_t *) NULL)
file->fdr.ilineBase
= last_file->fdr.ilineBase + last_file->fdr.cline;
else
file->fdr.ilineBase = 0;
file->fdr.cbLineOffset = c;
}
if (l->proc != proc)
{
proc = l->proc;
if (proc != (proc_t *) NULL)
{
proc->pdr.lnLow = l->lineno;
proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset;
proc->pdr.iline = totcount;
}
}
last = (lineno_list_t *) NULL;
}
totcount += count;
if (last == (lineno_list_t *) NULL)
delta = 0;
else
delta = l->lineno - last->lineno;
while (delta != 0)
{
int setcount;
--count;
if (count <= 0x0f)
{
setcount = count;
count = 0;
}
else
{
setcount = 0x0f;
count -= 0x0f;
}
if (delta >= -7 && delta <= 7)
{
if (bufptr >= *bufend)
bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
*bufptr++ = setcount + (delta << 4);
delta = 0;
++c;
}
else
{
int set;
if (*bufend - bufptr < 3)
bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3);
*bufptr++ = setcount + (8 << 4);
if (delta < -0x8000)
{
set = -0x8000;
delta += 0x8000;
}
else if (delta > 0x7fff)
{
set = 0x7fff;
delta -= 0x7fff;
}
else
{
set = delta;
delta = 0;
}
*bufptr++ = set >> 8;
*bufptr++ = set & 0xffff;
c += 3;
}
}
while (count > 0)
{
if (bufptr >= *bufend)
bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
--count;
if (count > 0x0f)
{
*bufptr++ = 0x0f;
count -= 0x0f;
}
else
{
*bufptr++ = count;
count = 0;
}
++c;
}
++iline;
last = l;
}
if (proc != (proc_t *) NULL)
proc->pdr.lnHigh = last->lineno;
if (file != (efdr_t *) NULL)
{
file->fdr.cbLine = c - file->fdr.cbLineOffset;
file->fdr.cline = totcount;
}
if (linecntptr != (long *) NULL)
*linecntptr += totcount;
c = ecoff_padding_adjust (backend, buf, bufend, c, &bufptr);
return c;
}
static unsigned long
ecoff_build_symbols (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset)
{
const bfd_size_type external_sym_size = backend->external_sym_size;
void (* const swap_sym_out) (bfd *, const SYMR *, PTR)
= backend->swap_sym_out;
char *sym_out;
long isym;
vlinks_t *file_link;
sym_out = *buf + offset;
isym = 0;
for (file_link = file_desc.first;
file_link != (vlinks_t *) NULL;
file_link = file_link->next)
{
int ifilesym;
int fil_cnt;
efdr_t *fil_ptr;
efdr_t *fil_end;
if (file_link->next == (vlinks_t *) NULL)
fil_cnt = file_desc.objects_last_page;
else
fil_cnt = file_desc.objects_per_page;
fil_ptr = file_link->datum->file;
fil_end = fil_ptr + fil_cnt;
for (; fil_ptr < fil_end; fil_ptr++)
{
vlinks_t *sym_link;
fil_ptr->fdr.isymBase = isym;
ifilesym = isym;
for (sym_link = fil_ptr->symbols.first;
sym_link != (vlinks_t *) NULL;
sym_link = sym_link->next)
{
int sym_cnt;
localsym_t *sym_ptr;
localsym_t *sym_end;
if (sym_link->next == (vlinks_t *) NULL)
sym_cnt = fil_ptr->symbols.objects_last_page;
else
sym_cnt = fil_ptr->symbols.objects_per_page;
sym_ptr = sym_link->datum->sym;
sym_end = sym_ptr + sym_cnt;
for (; sym_ptr < sym_end; sym_ptr++)
{
int local;
symbolS *as_sym;
forward_t *f;
know (sym_ptr->file_ptr == fil_ptr);
local = 1;
as_sym = sym_ptr->as_sym;
if (as_sym != (symbolS *) NULL)
{
symint_t indx;
if (sym_ptr->ecoff_sym.asym.st == (int) st_Block
&& sym_ptr->ecoff_sym.asym.sc == (int) sc_Text)
{
symbolS *begin_sym;
know (sym_ptr->proc_ptr != (proc_t *) NULL);
begin_sym = sym_ptr->proc_ptr->sym->as_sym;
if (S_GET_SEGMENT (as_sym)
!= S_GET_SEGMENT (begin_sym))
as_warn (_(".begin/.bend in different segments"));
sym_ptr->ecoff_sym.asym.value =
S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
}
else
sym_ptr->ecoff_sym.asym.value =
(S_GET_VALUE (as_sym)
+ bfd_get_section_vma (stdoutput,
S_GET_SEGMENT (as_sym))
+ sym_ptr->addend);
sym_ptr->ecoff_sym.weakext = S_IS_WEAK (as_sym);
if (sym_ptr->ecoff_sym.asym.st == st_Proc
&& S_IS_DEFINED (as_sym)
&& ! S_IS_EXTERNAL (as_sym)
&& ! S_IS_WEAK (as_sym))
sym_ptr->ecoff_sym.asym.st = st_StaticProc;
indx = sym_ptr->ecoff_sym.asym.index;
if (sym_ptr->ecoff_sym.asym.st == st_Nil
&& sym_ptr->ecoff_sym.asym.sc == sc_Nil
&& (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
|| ((ECOFF_UNMARK_STAB (indx) != N_LBRAC)
&& (ECOFF_UNMARK_STAB (indx) != N_RBRAC))))
{
segT seg;
const char *segname;
st_t st;
sc_t sc;
seg = S_GET_SEGMENT (as_sym);
segname = segment_name (seg);
if (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
&& (S_IS_EXTERNAL (as_sym)
|| S_IS_WEAK (as_sym)
|| ! S_IS_DEFINED (as_sym)))
{
if ((symbol_get_bfdsym (as_sym)->flags
& BSF_FUNCTION) != 0)
st = st_Proc;
else
st = st_Global;
}
else if (seg == text_section)
st = st_Label;
else
st = st_Static;
if (! S_IS_DEFINED (as_sym))
{
valueT s;
s = symbol_get_obj (as_sym)->ecoff_extern_size;
if (s == 0
|| s > bfd_get_gp_size (stdoutput))
sc = sc_Undefined;
else
{
sc = sc_SUndefined;
sym_ptr->ecoff_sym.asym.value = s;
}
#ifdef S_SET_SIZE
S_SET_SIZE (as_sym, s);
#endif
}
else if (S_IS_COMMON (as_sym))
{
if (S_GET_VALUE (as_sym) > 0
&& (S_GET_VALUE (as_sym)
<= bfd_get_gp_size (stdoutput)))
sc = sc_SCommon;
else
sc = sc_Common;
}
else if (seg == text_section)
sc = sc_Text;
else if (seg == data_section)
sc = sc_Data;
else if (strcmp (segname, ".rdata") == 0
|| strcmp (segname, ".rodata") == 0)
sc = sc_RData;
else if (strcmp (segname, ".sdata") == 0)
sc = sc_SData;
else if (seg == bss_section)
sc = sc_Bss;
else if (strcmp (segname, ".sbss") == 0)
sc = sc_SBss;
else if (seg == &bfd_abs_section)
sc = sc_Abs;
else
{
sc = sc_Data;
}
sym_ptr->ecoff_sym.asym.st = (int) st;
sym_ptr->ecoff_sym.asym.sc = (int) sc;
}
if ((S_IS_EXTERNAL (as_sym)
|| S_IS_WEAK (as_sym)
|| ! S_IS_DEFINED (as_sym))
&& sym_ptr->proc_ptr == (proc_t *) NULL
&& sym_ptr->ecoff_sym.asym.st != (int) st_Nil
&& ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym))
local = 0;
if (S_IS_COMMON (as_sym))
local = 0;
if (local
&& sym_ptr->ecoff_sym.asym.st != st_End
&& strchr (sym_ptr->name, '\001') == 0)
sym_ptr->ecoff_sym.asym.iss =
add_string (&fil_ptr->strings,
fil_ptr->str_hash,
sym_ptr->name,
(shash_t **) NULL);
}
if (sym_ptr->begin_ptr != (localsym_t *) NULL)
{
localsym_t *begin_ptr;
st_t begin_type;
know (local);
begin_ptr = sym_ptr->begin_ptr;
know (begin_ptr->sym_index != -1);
sym_ptr->ecoff_sym.asym.index = begin_ptr->sym_index;
if (sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
sym_ptr->ecoff_sym.asym.iss =
begin_ptr->ecoff_sym.asym.iss;
begin_type = begin_ptr->ecoff_sym.asym.st;
if (begin_type == st_File
|| begin_type == st_Block)
{
begin_ptr->ecoff_sym.asym.index =
isym - ifilesym + 1;
(*swap_sym_out) (stdoutput,
&begin_ptr->ecoff_sym.asym,
(*buf
+ offset
+ (begin_ptr->sym_index
* external_sym_size)));
}
else
{
know (begin_ptr->index_ptr != (aux_t *) NULL);
begin_ptr->index_ptr->data.isym =
isym - ifilesym + 1;
}
if (begin_type == st_Proc
|| begin_type == st_StaticProc)
{
know (as_sym != (symbolS *) NULL);
know (begin_ptr->as_sym != (symbolS *) NULL);
if (S_GET_SEGMENT (as_sym)
!= S_GET_SEGMENT (begin_ptr->as_sym))
as_warn (_(".begin/.bend in different segments"));
sym_ptr->ecoff_sym.asym.value =
(S_GET_VALUE (as_sym)
- S_GET_VALUE (begin_ptr->as_sym));
if ((sym_ptr->ecoff_sym.asym.value & 1) != 0)
++sym_ptr->ecoff_sym.asym.value;
#ifdef S_SET_SIZE
S_SET_SIZE (begin_ptr->as_sym,
sym_ptr->ecoff_sym.asym.value);
#endif
}
else if (begin_type == st_Block
&& sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
{
symbolS *begin_sym;
know (as_sym != (symbolS *) NULL);
know (sym_ptr->proc_ptr != (proc_t *) NULL);
begin_sym = sym_ptr->proc_ptr->sym->as_sym;
if (S_GET_SEGMENT (as_sym)
!= S_GET_SEGMENT (begin_sym))
as_warn (_(".begin/.bend in different segments"));
sym_ptr->ecoff_sym.asym.value =
S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
}
}
for (f = sym_ptr->forward_ref;
f != (forward_t *) NULL;
f = f->next)
{
know (local);
f->ifd_ptr->data.isym = fil_ptr->file_index;
f->index_ptr->data.rndx.index = isym - ifilesym;
}
if (local)
{
if ((bfd_size_type)(*bufend - sym_out) < external_sym_size)
sym_out = ecoff_add_bytes (buf, bufend,
sym_out,
external_sym_size);
(*swap_sym_out) (stdoutput, &sym_ptr->ecoff_sym.asym,
sym_out);
sym_out += external_sym_size;
sym_ptr->sym_index = isym;
if (sym_ptr->proc_ptr != (proc_t *) NULL
&& sym_ptr->proc_ptr->sym == sym_ptr)
sym_ptr->proc_ptr->pdr.isym = isym - ifilesym;
++isym;
}
if (as_sym != (symbolS *) NULL
&& symbol_get_obj (as_sym)->ecoff_symbol == sym_ptr)
{
if ((sym_ptr->ecoff_sym.asym.st == st_Proc
|| sym_ptr->ecoff_sym.asym.st == st_StaticProc)
&& local)
sym_ptr->ecoff_sym.asym.index = isym - ifilesym - 1;
sym_ptr->ecoff_sym.ifd = fil_ptr->file_index;
if (S_IS_EXTERNAL (as_sym) || S_IS_WEAK (as_sym))
fil_ptr->fdr.fMerge = 0;
}
}
}
fil_ptr->fdr.csym = isym - fil_ptr->fdr.isymBase;
}
}
return offset + isym * external_sym_size;
}
static unsigned long
ecoff_build_procs (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset)
{
const bfd_size_type external_pdr_size = backend->external_pdr_size;
void (* const swap_pdr_out) (bfd *, const PDR *, PTR)
= backend->swap_pdr_out;
char *pdr_out;
long iproc;
vlinks_t *file_link;
pdr_out = *buf + offset;
iproc = 0;
for (file_link = file_desc.first;
file_link != (vlinks_t *) NULL;
file_link = file_link->next)
{
int fil_cnt;
efdr_t *fil_ptr;
efdr_t *fil_end;
if (file_link->next == (vlinks_t *) NULL)
fil_cnt = file_desc.objects_last_page;
else
fil_cnt = file_desc.objects_per_page;
fil_ptr = file_link->datum->file;
fil_end = fil_ptr + fil_cnt;
for (; fil_ptr < fil_end; fil_ptr++)
{
vlinks_t *proc_link;
int first;
fil_ptr->fdr.ipdFirst = iproc;
first = 1;
for (proc_link = fil_ptr->procs.first;
proc_link != (vlinks_t *) NULL;
proc_link = proc_link->next)
{
int prc_cnt;
proc_t *proc_ptr;
proc_t *proc_end;
if (proc_link->next == (vlinks_t *) NULL)
prc_cnt = fil_ptr->procs.objects_last_page;
else
prc_cnt = fil_ptr->procs.objects_per_page;
proc_ptr = proc_link->datum->proc;
proc_end = proc_ptr + prc_cnt;
for (; proc_ptr < proc_end; proc_ptr++)
{
symbolS *adr_sym;
unsigned long adr;
adr_sym = proc_ptr->sym->as_sym;
adr = (S_GET_VALUE (adr_sym)
+ bfd_get_section_vma (stdoutput,
S_GET_SEGMENT (adr_sym)));
if (first)
{
fil_ptr->fdr.adr = adr;
first = 0;
}
proc_ptr->pdr.adr = adr - fil_ptr->fdr.adr;
if ((bfd_size_type)(*bufend - pdr_out) < external_pdr_size)
pdr_out = ecoff_add_bytes (buf, bufend,
pdr_out,
external_pdr_size);
(*swap_pdr_out) (stdoutput, &proc_ptr->pdr, pdr_out);
pdr_out += external_pdr_size;
++iproc;
}
}
fil_ptr->fdr.cpd = iproc - fil_ptr->fdr.ipdFirst;
}
}
return offset + iproc * external_pdr_size;
}
static unsigned long
ecoff_build_aux (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset)
{
int bigendian;
union aux_ext *aux_out;
long iaux;
vlinks_t *file_link;
bigendian = bfd_big_endian (stdoutput);
aux_out = (union aux_ext *) (*buf + offset);
iaux = 0;
for (file_link = file_desc.first;
file_link != (vlinks_t *) NULL;
file_link = file_link->next)
{
int fil_cnt;
efdr_t *fil_ptr;
efdr_t *fil_end;
if (file_link->next == (vlinks_t *) NULL)
fil_cnt = file_desc.objects_last_page;
else
fil_cnt = file_desc.objects_per_page;
fil_ptr = file_link->datum->file;
fil_end = fil_ptr + fil_cnt;
for (; fil_ptr < fil_end; fil_ptr++)
{
vlinks_t *aux_link;
fil_ptr->fdr.fBigendian = bigendian;
fil_ptr->fdr.iauxBase = iaux;
for (aux_link = fil_ptr->aux_syms.first;
aux_link != (vlinks_t *) NULL;
aux_link = aux_link->next)
{
int aux_cnt;
aux_t *aux_ptr;
aux_t *aux_end;
if (aux_link->next == (vlinks_t *) NULL)
aux_cnt = fil_ptr->aux_syms.objects_last_page;
else
aux_cnt = fil_ptr->aux_syms.objects_per_page;
aux_ptr = aux_link->datum->aux;
aux_end = aux_ptr + aux_cnt;
for (; aux_ptr < aux_end; aux_ptr++)
{
if ((unsigned long) (*bufend - (char *) aux_out)
< sizeof (union aux_ext))
aux_out = ((union aux_ext *)
ecoff_add_bytes (buf, bufend,
(char *) aux_out,
sizeof (union aux_ext)));
switch (aux_ptr->type)
{
case aux_tir:
(*backend->swap_tir_out) (bigendian,
&aux_ptr->data.ti,
&aux_out->a_ti);
break;
case aux_rndx:
(*backend->swap_rndx_out) (bigendian,
&aux_ptr->data.rndx,
&aux_out->a_rndx);
break;
case aux_dnLow:
AUX_PUT_DNLOW (bigendian, aux_ptr->data.dnLow,
aux_out);
break;
case aux_dnHigh:
AUX_PUT_DNHIGH (bigendian, aux_ptr->data.dnHigh,
aux_out);
break;
case aux_isym:
AUX_PUT_ISYM (bigendian, aux_ptr->data.isym,
aux_out);
break;
case aux_iss:
AUX_PUT_ISS (bigendian, aux_ptr->data.iss,
aux_out);
break;
case aux_width:
AUX_PUT_WIDTH (bigendian, aux_ptr->data.width,
aux_out);
break;
case aux_count:
AUX_PUT_COUNT (bigendian, aux_ptr->data.count,
aux_out);
break;
}
++aux_out;
++iaux;
}
}
fil_ptr->fdr.caux = iaux - fil_ptr->fdr.iauxBase;
}
}
return ecoff_padding_adjust (backend, buf, bufend,
offset + iaux * sizeof (union aux_ext),
(char **) NULL);
}
static unsigned long
ecoff_build_strings (char **buf,
char **bufend,
unsigned long offset,
varray_t *vp)
{
unsigned long istr;
char *str_out;
vlinks_t *str_link;
str_out = *buf + offset;
istr = 0;
for (str_link = vp->first;
str_link != (vlinks_t *) NULL;
str_link = str_link->next)
{
unsigned long str_cnt;
if (str_link->next == (vlinks_t *) NULL)
str_cnt = vp->objects_last_page;
else
str_cnt = vp->objects_per_page;
if ((unsigned long)(*bufend - str_out) < str_cnt)
str_out = ecoff_add_bytes (buf, bufend, str_out, str_cnt);
memcpy (str_out, str_link->datum->byte, str_cnt);
str_out += str_cnt;
istr += str_cnt;
}
return istr;
}
static unsigned long
ecoff_build_ss (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset)
{
long iss;
vlinks_t *file_link;
iss = 0;
for (file_link = file_desc.first;
file_link != (vlinks_t *) NULL;
file_link = file_link->next)
{
int fil_cnt;
efdr_t *fil_ptr;
efdr_t *fil_end;
if (file_link->next == (vlinks_t *) NULL)
fil_cnt = file_desc.objects_last_page;
else
fil_cnt = file_desc.objects_per_page;
fil_ptr = file_link->datum->file;
fil_end = fil_ptr + fil_cnt;
for (; fil_ptr < fil_end; fil_ptr++)
{
long ss_cnt;
fil_ptr->fdr.issBase = iss;
ss_cnt = ecoff_build_strings (buf, bufend, offset + iss,
&fil_ptr->strings);
fil_ptr->fdr.cbSs = ss_cnt;
iss += ss_cnt;
}
}
return ecoff_padding_adjust (backend, buf, bufend, offset + iss,
(char **) NULL);
}
static unsigned long
ecoff_build_fdr (const struct ecoff_debug_swap *backend,
char **buf,
char **bufend,
unsigned long offset)
{
const bfd_size_type external_fdr_size = backend->external_fdr_size;
void (* const swap_fdr_out) (bfd *, const FDR *, PTR)
= backend->swap_fdr_out;
long ifile;
char *fdr_out;
vlinks_t *file_link;
ifile = 0;
fdr_out = *buf + offset;
for (file_link = file_desc.first;
file_link != (vlinks_t *) NULL;
file_link = file_link->next)
{
int fil_cnt;
efdr_t *fil_ptr;
efdr_t *fil_end;
if (file_link->next == (vlinks_t *) NULL)
fil_cnt = file_desc.objects_last_page;
else
fil_cnt = file_desc.objects_per_page;
fil_ptr = file_link->datum->file;
fil_end = fil_ptr + fil_cnt;
for (; fil_ptr < fil_end; fil_ptr++)
{
if ((bfd_size_type)(*bufend - fdr_out) < external_fdr_size)
fdr_out = ecoff_add_bytes (buf, bufend, fdr_out,
external_fdr_size);
(*swap_fdr_out) (stdoutput, &fil_ptr->fdr, fdr_out);
fdr_out += external_fdr_size;
++ifile;
}
}
return offset + ifile * external_fdr_size;
}
static void
ecoff_setup_ext (void)
{
register symbolS *sym;
for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
{
if (symbol_get_obj (sym)->ecoff_symbol == NULL)
continue;
if (! S_IS_EXTERNAL (sym)
&& ! S_IS_WEAK (sym)
&& S_IS_DEFINED (sym))
{
struct localsym *lsym;
lsym = symbol_get_obj (sym)->ecoff_symbol;
lsym->ecoff_sym.asym.value = 0;
lsym->ecoff_sym.asym.st = (int) st_Nil;
lsym->ecoff_sym.asym.sc = (int) sc_Nil;
lsym->ecoff_sym.asym.index = indexNil;
}
obj_ecoff_set_ext (sym, &symbol_get_obj (sym)->ecoff_symbol->ecoff_sym);
}
}
unsigned long
ecoff_build_debug (HDRR *hdr,
char **bufp,
const struct ecoff_debug_swap *backend)
{
const bfd_size_type external_pdr_size = backend->external_pdr_size;
tag_t *ptag;
tag_t *ptag_next;
efdr_t *fil_ptr;
int end_warning;
efdr_t *hold_file_ptr;
proc_t *hold_proc_ptr;
symbolS *sym;
char *buf;
char *bufend;
unsigned long offset;
if (first_file == (efdr_t *) NULL)
add_file ((const char *) NULL, 0, 1);
for (ptag = top_tag_head->first_tag;
ptag != (tag_t *) NULL;
ptag = ptag_next)
{
if (ptag->forward_ref != (forward_t *) NULL)
add_unknown_tag (ptag);
ptag_next = ptag->same_block;
ptag->hash_ptr->tag_ptr = ptag->same_name;
free_tag (ptag);
}
free_thead (top_tag_head);
hold_file_ptr = cur_file_ptr;
hold_proc_ptr = cur_proc_ptr;
cur_proc_ptr = (proc_t *) NULL;
for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
{
if (symbol_get_obj (sym)->ecoff_symbol != NULL
|| symbol_get_obj (sym)->ecoff_file == (efdr_t *) NULL
|| (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0)
continue;
cur_file_ptr = symbol_get_obj (sym)->ecoff_file;
add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
(bfd_vma) 0, S_GET_VALUE (sym), indexNil);
}
cur_proc_ptr = hold_proc_ptr;
cur_file_ptr = hold_file_ptr;
end_warning = 0;
for (fil_ptr = first_file;
fil_ptr != (efdr_t *) NULL;
fil_ptr = fil_ptr->next_file)
{
cur_file_ptr = fil_ptr;
while (cur_file_ptr->cur_scope != (scope_t *) NULL
&& cur_file_ptr->cur_scope->prev != (scope_t *) NULL)
{
cur_file_ptr->cur_scope = cur_file_ptr->cur_scope->prev;
if (! end_warning && ! cur_file_ptr->fake)
{
as_warn (_("missing .end or .bend at end of file"));
end_warning = 1;
}
}
if (cur_file_ptr->cur_scope != (scope_t *) NULL)
(void) add_ecoff_symbol ((const char *) NULL,
st_End, sc_Text,
(symbolS *) NULL,
(bfd_vma) 0,
(symint_t) 0,
(symint_t) 0);
}
offset = 0;
buf = xmalloc (PAGE_SIZE);
bufend = buf + PAGE_SIZE;
hdr->cbLineOffset = offset;
offset = ecoff_build_lineno (backend, &buf, &bufend, offset,
&hdr->ilineMax);
hdr->cbLine = offset - hdr->cbLineOffset;
hdr->idnMax = 0;
hdr->cbDnOffset = 0;
hdr->ipdMax = proc_cnt;
hdr->cbPdOffset = offset;
if ((bfd_size_type)(bufend - (buf + offset)) < proc_cnt * external_pdr_size)
(void) ecoff_add_bytes (&buf, &bufend, buf + offset,
proc_cnt * external_pdr_size);
offset += proc_cnt * external_pdr_size;
hdr->cbSymOffset = offset;
offset = ecoff_build_symbols (backend, &buf, &bufend, offset);
hdr->isymMax = (offset - hdr->cbSymOffset) / backend->external_sym_size;
(void) ecoff_build_procs (backend, &buf, &bufend, hdr->cbPdOffset);
hdr->ioptMax = 0;
hdr->cbOptOffset = 0;
hdr->cbAuxOffset = offset;
offset = ecoff_build_aux (backend, &buf, &bufend, offset);
hdr->iauxMax = (offset - hdr->cbAuxOffset) / sizeof (union aux_ext);
hdr->cbSsOffset = offset;
offset = ecoff_build_ss (backend, &buf, &bufend, offset);
hdr->issMax = offset - hdr->cbSsOffset;
hdr->crfd = 0;
hdr->cbRfdOffset = 0;
hdr->cbFdOffset = offset;
offset = ecoff_build_fdr (backend, &buf, &bufend, offset);
hdr->ifdMax = (offset - hdr->cbFdOffset) / backend->external_fdr_size;
hdr->issExtMax = 0;
hdr->cbSsExtOffset = 0;
hdr->iextMax = 0;
hdr->cbExtOffset = 0;
ecoff_setup_ext ();
know ((offset & (backend->debug_align - 1)) == 0);
#ifdef TC_ALPHA
hdr->vstamp = 0x030b;
#else
hdr->vstamp = 0x020b;
#endif
*bufp = buf;
return offset;
}
#ifndef MALLOC_CHECK
static page_type *
allocate_cluster (unsigned long npages)
{
register page_type *value = (page_type *) xmalloc (npages * PAGE_USIZE);
#ifdef ECOFF_DEBUG
if (debug > 3)
fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
#endif
memset (value, 0, npages * PAGE_USIZE);
return value;
}
static page_type *cluster_ptr = NULL;
static unsigned long pages_left = 0;
#endif
static page_type *
allocate_page (void)
{
#ifndef MALLOC_CHECK
if (pages_left == 0)
{
pages_left = MAX_CLUSTER_PAGES;
cluster_ptr = allocate_cluster (pages_left);
}
pages_left--;
return cluster_ptr++;
#else
page_type *ptr;
ptr = xmalloc (PAGE_USIZE);
memset (ptr, 0, PAGE_USIZE);
return ptr;
#endif
}
static scope_t *
allocate_scope (void)
{
register scope_t *ptr;
static scope_t initial_scope;
#ifndef MALLOC_CHECK
ptr = alloc_counts[(int) alloc_type_scope].free_list.f_scope;
if (ptr != (scope_t *) NULL)
alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr->free;
else
{
register int unallocated = alloc_counts[(int) alloc_type_scope].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_scope].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (scope_t);
alloc_counts[(int) alloc_type_scope].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_scope].total_pages++;
}
ptr = &cur_page->scope[--unallocated];
alloc_counts[(int) alloc_type_scope].unallocated = unallocated;
}
#else
ptr = (scope_t *) xmalloc (sizeof (scope_t));
#endif
alloc_counts[(int) alloc_type_scope].total_alloc++;
*ptr = initial_scope;
return ptr;
}
static void
free_scope (scope_t *ptr)
{
alloc_counts[(int) alloc_type_scope].total_free++;
#ifndef MALLOC_CHECK
ptr->free = alloc_counts[(int) alloc_type_scope].free_list.f_scope;
alloc_counts[(int) alloc_type_scope].free_list.f_scope = ptr;
#else
free ((PTR) ptr);
#endif
}
static vlinks_t *
allocate_vlinks (void)
{
register vlinks_t *ptr;
static vlinks_t initial_vlinks;
#ifndef MALLOC_CHECK
register int unallocated = alloc_counts[(int) alloc_type_vlinks].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_vlinks].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (vlinks_t);
alloc_counts[(int) alloc_type_vlinks].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_vlinks].total_pages++;
}
ptr = &cur_page->vlinks[--unallocated];
alloc_counts[(int) alloc_type_vlinks].unallocated = unallocated;
#else
ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
#endif
alloc_counts[(int) alloc_type_vlinks].total_alloc++;
*ptr = initial_vlinks;
return ptr;
}
static shash_t *
allocate_shash (void)
{
register shash_t *ptr;
static shash_t initial_shash;
#ifndef MALLOC_CHECK
register int unallocated = alloc_counts[(int) alloc_type_shash].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_shash].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (shash_t);
alloc_counts[(int) alloc_type_shash].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_shash].total_pages++;
}
ptr = &cur_page->shash[--unallocated];
alloc_counts[(int) alloc_type_shash].unallocated = unallocated;
#else
ptr = (shash_t *) xmalloc (sizeof (shash_t));
#endif
alloc_counts[(int) alloc_type_shash].total_alloc++;
*ptr = initial_shash;
return ptr;
}
static thash_t *
allocate_thash (void)
{
register thash_t *ptr;
static thash_t initial_thash;
#ifndef MALLOC_CHECK
register int unallocated = alloc_counts[(int) alloc_type_thash].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_thash].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (thash_t);
alloc_counts[(int) alloc_type_thash].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_thash].total_pages++;
}
ptr = &cur_page->thash[--unallocated];
alloc_counts[(int) alloc_type_thash].unallocated = unallocated;
#else
ptr = (thash_t *) xmalloc (sizeof (thash_t));
#endif
alloc_counts[(int) alloc_type_thash].total_alloc++;
*ptr = initial_thash;
return ptr;
}
static tag_t *
allocate_tag (void)
{
register tag_t *ptr;
static tag_t initial_tag;
#ifndef MALLOC_CHECK
ptr = alloc_counts[(int) alloc_type_tag].free_list.f_tag;
if (ptr != (tag_t *) NULL)
alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr->free;
else
{
register int unallocated = alloc_counts[(int) alloc_type_tag].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_tag].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (tag_t);
alloc_counts[(int) alloc_type_tag].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_tag].total_pages++;
}
ptr = &cur_page->tag[--unallocated];
alloc_counts[(int) alloc_type_tag].unallocated = unallocated;
}
#else
ptr = (tag_t *) xmalloc (sizeof (tag_t));
#endif
alloc_counts[(int) alloc_type_tag].total_alloc++;
*ptr = initial_tag;
return ptr;
}
static void
free_tag (tag_t *ptr)
{
alloc_counts[(int) alloc_type_tag].total_free++;
#ifndef MALLOC_CHECK
ptr->free = alloc_counts[(int) alloc_type_tag].free_list.f_tag;
alloc_counts[(int) alloc_type_tag].free_list.f_tag = ptr;
#else
free ((PTR_T) ptr);
#endif
}
static forward_t *
allocate_forward (void)
{
register forward_t *ptr;
static forward_t initial_forward;
#ifndef MALLOC_CHECK
register int unallocated = alloc_counts[(int) alloc_type_forward].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_forward].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (forward_t);
alloc_counts[(int) alloc_type_forward].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_forward].total_pages++;
}
ptr = &cur_page->forward[--unallocated];
alloc_counts[(int) alloc_type_forward].unallocated = unallocated;
#else
ptr = (forward_t *) xmalloc (sizeof (forward_t));
#endif
alloc_counts[(int) alloc_type_forward].total_alloc++;
*ptr = initial_forward;
return ptr;
}
static thead_t *
allocate_thead (void)
{
register thead_t *ptr;
static thead_t initial_thead;
#ifndef MALLOC_CHECK
ptr = alloc_counts[(int) alloc_type_thead].free_list.f_thead;
if (ptr != (thead_t *) NULL)
alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr->free;
else
{
register int unallocated = alloc_counts[(int) alloc_type_thead].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_thead].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (thead_t);
alloc_counts[(int) alloc_type_thead].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_thead].total_pages++;
}
ptr = &cur_page->thead[--unallocated];
alloc_counts[(int) alloc_type_thead].unallocated = unallocated;
}
#else
ptr = (thead_t *) xmalloc (sizeof (thead_t));
#endif
alloc_counts[(int) alloc_type_thead].total_alloc++;
*ptr = initial_thead;
return ptr;
}
static void
free_thead (thead_t *ptr)
{
alloc_counts[(int) alloc_type_thead].total_free++;
#ifndef MALLOC_CHECK
ptr->free = (thead_t *) alloc_counts[(int) alloc_type_thead].free_list.f_thead;
alloc_counts[(int) alloc_type_thead].free_list.f_thead = ptr;
#else
free ((PTR_T) ptr);
#endif
}
static lineno_list_t *
allocate_lineno_list (void)
{
register lineno_list_t *ptr;
static lineno_list_t initial_lineno_list;
#ifndef MALLOC_CHECK
register int unallocated = alloc_counts[(int) alloc_type_lineno].unallocated;
register page_type *cur_page = alloc_counts[(int) alloc_type_lineno].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (lineno_list_t);
alloc_counts[(int) alloc_type_lineno].cur_page = cur_page = allocate_page ();
alloc_counts[(int) alloc_type_lineno].total_pages++;
}
ptr = &cur_page->lineno[--unallocated];
alloc_counts[(int) alloc_type_lineno].unallocated = unallocated;
#else
ptr = (lineno_list_t *) xmalloc (sizeof (lineno_list_t));
#endif
alloc_counts[(int) alloc_type_lineno].total_alloc++;
*ptr = initial_lineno_list;
return ptr;
}
void
ecoff_set_gp_prolog_size (int sz)
{
if (cur_proc_ptr == 0)
return;
cur_proc_ptr->pdr.gp_prologue = sz;
if (cur_proc_ptr->pdr.gp_prologue != sz)
{
as_warn (_("GP prologue size exceeds field size, using 0 instead"));
cur_proc_ptr->pdr.gp_prologue = 0;
}
cur_proc_ptr->pdr.gp_used = 1;
}
int
ecoff_no_current_file (void)
{
return cur_file_ptr == (efdr_t *) NULL;
}
void
ecoff_generate_asm_lineno (void)
{
unsigned int lineno;
char *filename;
lineno_list_t *list;
as_where (&filename, &lineno);
if (current_stabs_filename == (char *) NULL
|| strcmp (current_stabs_filename, filename))
add_file (filename, 0, 1);
list = allocate_lineno_list ();
list->next = (lineno_list_t *) NULL;
list->file = cur_file_ptr;
list->proc = cur_proc_ptr;
list->frag = frag_now;
list->paddr = frag_now_fix ();
list->lineno = lineno;
cur_file_ptr->fdr.fMerge = 0;
if (cur_proc_ptr == (proc_t *) NULL)
{
lineno_list_t **pl;
pl = &noproc_lineno;
while (*pl != (lineno_list_t *) NULL)
pl = &(*pl)->next;
*pl = list;
}
else
{
last_lineno = list;
*last_lineno_ptr = list;
last_lineno_ptr = &list->next;
}
}
#else
void
ecoff_generate_asm_lineno (void)
{
}
#endif