Changeset 534


Ignore:
Timestamp:
Aug 5, 2003, 8:54:32 PM (22 years ago)
Author:
bird
Message:

#483,#428: sorting, new weak handling, legacy mode.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/emx/src/emxexp/emxexp.c

    • Property cvs2svn:cvs-rev changed from 1.10 to 1.11
    r533 r534  
    3838};
    3939
     40/* if != 0 we're supposed to add ordinals to the symbols. */
    4041static int ordinal = 0;
     42/* if set the ordinals is to be sequentially assigned with no
     43   conveniency gaps or anything. */
     44static int ordinal_seq = FALSE;
    4145static int noname_flag = FALSE;
    4246static int bss_flag = FALSE;
    4347static int weak_flag = FALSE;
     48/* When clear we'll do sorting and handle make sure there no duplicate weak
     49   names and such. If set we'll just dump the publics and comdefs as we
     50   used to do. */
     51static int legacy_mode = FALSE;
    4452
    4553static FILE *out_file;
     
    5058static struct bss_list *bss_list = NULL;
    5159
     60/* OMF globals */
     61static struct segdef
     62{
     63    /* pointer to local name */
     64    const char *name;
     65}              *segdefs;
     66static unsigned num_segdefs;
     67static char **  lnames;
     68static unsigned num_lnames;
     69
     70/* Aout globals */
     71static char *aout_segnames[] =
     72{   
     73    NULL,     NULL,     /*  0 N_UNDF */   
     74    NULL,     NULL,     /*  2 N_ABS */
     75    "TEXT32", "TEXT32", /*  4 N_TEXT */   
     76    "DATA32", "DATA32", /*  6 N_DATA */   
     77    "BSS32",  "BSS32",  /*  8 N_BSS */     
     78    NULL,     NULL,     /*  a */
     79    NULL,     NULL,     /*  c,  d N_WEAKU */
     80    NULL,     "TEXT32", /*  d N_WEAKA,  f N_WEAKT */
     81    "DATA32", "BSS32",  /* 10 N_WEAKD, 11 N_WEAKB */
     82    NULL, NULL,  NULL, NULL, NULL
     83};
     84
     85/* Per segment name sorting
     86   Symbols are orginized in two constructs. One is a global symbol name
     87   string pool kind thing. The other is per segment.
     88   
     89   Weak symbols and communial data may be overridden. In those cases we'll
     90   unlink the symbol and reinstert it to ensure that we don't get it in the
     91   wrong segment.
     92   */
     93
     94/* module in which a symbol is defined. */
     95struct new_module
     96{
     97    char *              name;           /* module name. */
     98    struct new_module * next;           /* next module in the chain. */
     99};
     100
     101/* LIFO of modules. (only so we can free it)
     102   The head module is the current one. */
     103struct new_module      *new_modules;   
     104
     105
     106/* one symbol */
     107struct new_symbol
     108{
     109    char *              name;           /* Symbol name from heap. */
     110    struct new_symbol  *nexthash;       /* Next hash table entry. */
     111    struct new_symbol  *next, *prev;    /* Per segment chain. */
     112    struct new_module  *mod;            /* Module in which the symbol is defined. */
     113    unsigned            fweak:1;        /* Weak symbol. */
     114    unsigned            fcomm:1;        /* Communial data. */
     115    unsigned            fdummy:1;       /* Dummy node, the one which is first & last
     116                                           in the lists to save use from any
     117                                           unpleasant list head/tail thinking. */
     118};
     119
     120/* List of segments. */
     121static struct new_symgrp
     122{
     123    char *              name;           /* segment name */
     124    struct new_symbol  *head;           /* head of list. Always starts with a dummy node. */
     125    struct new_symbol  *tail;           /* tail of list. Always starts with a dummy node. */
     126    struct new_symgrp  *next;           /* next segement. */
     127}                 * new_symgrps;
     128
     129/* symbol string hash table */
     130struct new_symbol *  new_hashtable[211];
     131
     132
     133
    52134static void error (const char *fmt, ...) NORETURN2;
    53135static void usage (void) NORETURN2;
     
    75157
    76158  p = malloc (n);
    77   if (p == NULL)
     159  if (p == NULL && n)
    78160    error ("Out of memory");
    79161  return p;
     
    90172
    91173  p = realloc (ptr, n);
    92   if (p == NULL)
     174  if (p == NULL && n)
    93175    error ("Out of memory");
    94176  return p;
    95177}
     178
     179
     180/* Create a duplicate of the string S on the heap.  Quit on failure.
     181   This function is used like strdup(), but we don't have to check the
     182   return value. */
     183
     184char *xstrdup (const char *s)
     185{
     186  char *p;
     187
     188  p = xmalloc (strlen (s) + 1);
     189  strcpy (p, s);
     190  return p;
     191}
     192
    96193
    97194
     
    106203         "  -o          Output ordinal numbers, starting at 1\n"
    107204         "  -o<ordinal> Output ordinal numbers, starting at <ordinal>\n"
    108          "  -u          Also export uninitialized variables\n"
    109          "  -w          Allow export of weak symbols\n",
     205         "  -u          Also export uninitialized variables - only legacy mode\n"
     206         "  -w          Allow export of weak symbols - only legacy mode\n"
     207         "  -l          Legacy mode - disables sorting and weak handling\n",
    110208         stderr);
    111209  exit (1);
     210}
     211
     212
     213/* New export function. This will filter out duplicated BSS32 and weak
     214   symbols and insert the symbols into arrays according to segment
     215   value. new_print() will be called when all the input files are
     216   processed and do the actual printing and ordinal assignments. */
     217   
     218static void new_export (const char *name, const char *segname, int fweak, int fcomm)
     219{
     220  struct new_symbol  *psym;
     221  unsigned            uhash;
     222  const char *        psz;
     223
     224  /* compute hash */
     225  for (uhash = 0, psz = name; *psz; *psz++)
     226    uhash = uhash * 65599 + *psz;
     227  uhash %= sizeof(new_hashtable) / sizeof(new_hashtable[0]);
     228
     229  /* look for it */
     230  for (psym = new_hashtable[uhash]; psym; psym = psym->nexthash)
     231    if (!strcmp(psym->name, name))
     232        break;
     233
     234  /* new */
     235  if (!psym)
     236    {
     237      /* create new symbol node */
     238      psym = xmalloc(sizeof(*psym));
     239      psym->name = xstrdup(name);
     240
     241      /* insert into hash */
     242      psym->nexthash = new_hashtable[uhash];
     243      new_hashtable[uhash] = psym;
     244    }
     245  else
     246    {/* existing. look for overrided symbols (weak/comm) and ignore duplicates. */
     247      if (fweak || fcomm)
     248        psym = NULL;                  /* just skip it - did I forget something...? */
     249      else
     250        {
     251          if (psym->fcomm || psym->fweak)
     252            { /* unlink the symbol. */
     253              psym->prev->next = psym->next;
     254              psym->next->prev = psym->prev;
     255            }
     256          else
     257            psym = NULL;
     258        }
     259    }
     260
     261  /* insert the correct list */
     262  if (psym)
     263    {
     264      struct new_symgrp *psymgrp;
     265
     266      /* Set symbol data */
     267      psym->fcomm = fcomm;
     268      psym->fweak = fweak;
     269      psym->fdummy = 0;
     270      psym->mod = new_modules;               
     271
     272
     273      /* find the segment */
     274      for (psymgrp = new_symgrps; psymgrp; psymgrp = psymgrp->next)
     275        if (   psymgrp->name == segname
     276            || (segname && psymgrp->name && !strcmp(psymgrp->name, segname))
     277              )
     278           break;
     279
     280       /* new or old ? */
     281       if (!psymgrp)
     282         {
     283           psymgrp = xmalloc(sizeof(*psymgrp));
     284           psymgrp->name = segname ? xstrdup(segname) : NULL;
     285           psymgrp->head = xmalloc(sizeof(*psymgrp->head));
     286           psymgrp->tail = xmalloc(sizeof(*psymgrp->tail));
     287           memset(psymgrp->head, 0, sizeof(*psymgrp->head));
     288           memset(psymgrp->tail, 0, sizeof(*psymgrp->tail));
     289           psymgrp->head->fdummy = 1;
     290           psymgrp->tail->fdummy = 1;
     291           /* link dummies */
     292           psymgrp->head->next = psymgrp->tail;
     293           psymgrp->tail->prev = psymgrp->head;
     294           psymgrp->head->name = psymgrp->tail->name = "#;$$$$$$dummy$$$$$$$$$$$;#";
     295           /* link it in */
     296           psymgrp->next = new_symgrps;
     297           new_symgrps = psymgrp;
     298         }
     299
     300       /* insert at tail. */
     301       psym->prev = psymgrp->tail->prev;
     302       psym->next = psymgrp->tail;
     303       psymgrp->tail->prev->next = psym;
     304       psymgrp->tail->prev = psym;
     305    }
     306}
     307
     308
     309/* Print the publics. (new method)
     310
     311   When -o is not specified with number, to leave a round number of unused
     312   ordinals between the segments out of convenience mostly. */
     313
     314static void new_print(FILE *phfile, struct new_symgrp *psymgrp)
     315{
     316  /* enumerate symbol groups (segments) */
     317  for (; psymgrp; psymgrp = psymgrp->next)
     318    {
     319      struct new_symbol  *psym;
     320     
     321      /* print a decent header */
     322      if (psymgrp->name)
     323        fprintf (phfile, "  ; segment %s\n", psymgrp->name);
     324      else
     325        fprintf (phfile, "  ; segment noname\n");
     326
     327      /* enumerate symbols */
     328      for (psym = psymgrp->head->next; psym != psymgrp->tail; psym = psym->next)
     329        {
     330          int   cch;
     331
     332          cch = fprintf (phfile, "  \"%s\"", psym->name);
     333          /* fancy align */
     334          if (cch < 69)
     335              cch = 70 - cch;
     336          else if (cch < 89)
     337              cch = 90 - cch;
     338          else if (cch < 119)
     339              cch = 120 - cch;
     340          else
     341              cch = 40 - (cch % 39);
     342          fprintf (phfile, "%*s", cch, "");
     343
     344          /* flags */
     345          if (ordinal != 0)
     346            cch += fprintf (phfile, " @%-5d", ordinal++);
     347          if (noname_flag)
     348            cch += fprintf (phfile, " NONAME");
     349
     350          /* comments - the first one might be used by emximp later... */
     351          fprintf (phfile, "  ; magicseg='%s' len=%d",
     352                   psymgrp->name ? psymgrp->name : "", strlen(psym->name));
     353          if (psym->fweak)
     354              fprintf (phfile, "  weak");
     355          if (psym->fcomm)
     356              fprintf (phfile, "  comm");
     357          if (psym->mod)
     358              fprintf (phfile, "  mod='%s'", psym->mod->name);
     359
     360          fputc ('\n', phfile);
     361        }
     362     
     363      /* skip a line and some ordinals if we're allowed */
     364      fputc ('\n', phfile);
     365      if (!ordinal_seq)
     366        ordinal = ((ordinal + 199) / 100) * 100;
     367    }
    112368}
    113369
     
    200456    if (sym_ptr[i].n_type == (N_TEXT|N_EXT) ||
    201457        sym_ptr[i].n_type == (N_DATA|N_EXT) ||
    202         (weak_flag &&
     458        ((!legacy_mode || weak_flag) &&
    203459         (sym_ptr[i].n_type == N_WEAKT ||
    204460          sym_ptr[i].n_type == N_WEAKD)))
    205461      {
    206462        name = str_ptr + sym_ptr[i].n_un.n_strx;
    207         export (name);
     463        if (legacy_mode)
     464          export (name);
     465        else
     466          new_export (name, aout_segnames[sym_ptr[i].n_type],
     467                      sym_ptr[i].n_type >= N_WEAKU && sym_ptr[i].n_type >= N_WEAKB,
     468                      FALSE);
    208469      }
    209470    else if ((sym_ptr[i].n_type == N_EXT && sym_ptr[i].n_value != 0) ||
    210471             sym_ptr[i].n_type == (N_BSS|N_EXT) ||
    211              (weak_flag && sym_ptr[i].n_type == N_WEAKB))
     472             ((!legacy_mode || weak_flag) && sym_ptr[i].n_type == N_WEAKB))
    212473      {
    213474        name = str_ptr + sym_ptr[i].n_un.n_strx;
    214         export_bss (name);
     475        if (legacy_mode)
     476          export_bss (name);
     477        else
     478          new_export (name, aout_segnames[sym_ptr[i].n_type],
     479                      sym_ptr[i].n_type >= N_WEAKU && sym_ptr[i].n_type >= N_WEAKB,
     480                      TRUE);
    215481      }
    216482
     
    334600  word frame;
    335601  dword offset;
    336   byte name[256];
     602  byte name[260];
    337603
    338604  group = get_index ();
     
    343609  while (rec_idx < rec_len)
    344610    {
     611      char *weak;
    345612      get_string (name);
    346613      offset = get_word_or_dword ();
    347614      type = get_index ();
    348       export (name);
     615      weak = strstr(name, "$w$");
     616      if (legacy_mode)
     617        {
     618          if (!weak || weak_flag)
     619            export (name);
     620        }
     621      else
     622        {
     623          if (weak)
     624            {
     625              memmove(weak + 1, weak, strlen(weak) + 1);
     626              *weak++ = '\0';
     627            }
     628          new_export (name, segdefs[seg].name, weak != NULL, FALSE);
     629        }
    349630    }
    350631}
     
    354635{
    355636  int type_index, data_type;
    356   byte name[256];
     637  byte name[260];
    357638
    358639  while (rec_idx < rec_len)
    359640    {
     641      char *weak;
    360642      get_string (name);
    361643      type_index = get_index ();
     
    373655          bad_omf ();
    374656        }
    375       export_bss (name);
    376     }
    377 }
     657
     658      weak = strstr(name, "$w$");
     659      if (legacy_mode)
     660        {
     661          if (!weak || weak_flag)
     662            export_bss (name);
     663        }
     664      else
     665        {
     666          if (weak)
     667            {
     668              memmove(weak + 1, weak, strlen(weak) + 1);
     669              *weak++ = '\0';
     670            }
     671          new_export (name, "BSS32", weak != NULL, TRUE);
     672        }
     673    }
     674}
     675
     676
     677static void omf_lnames (void)
     678{
     679  while (rec_idx < rec_len)
     680    {
     681      unsigned len = get_byte ();
     682      if (!(num_lnames % 64))
     683        lnames = xrealloc(lnames, sizeof(lnames[0]) * (num_lnames + 64));
     684      lnames[num_lnames] = xmalloc(len + 1);
     685      get_mem(lnames[num_lnames], len);
     686      lnames[num_lnames][len] = '\0';
     687      num_lnames++;
     688    }
     689}
     690
     691
     692static void omf_segdef (void)
     693{
     694  byte      flags;
     695  unsigned  nameidx;
     696  unsigned  classidx;
     697  unsigned  ovlidx;
     698 
     699  /* all we want the the segment name */
     700  flags = get_byte ();                  /* segment attributes */
     701  if ((flags & 0xE0) == 0)
     702    {
     703      get_word ();                      /* frame number */
     704      get_byte ();                      /* offset */
     705    }
     706  if (rec_type & REC32)                 /* segment length */
     707    get_dword ();                       
     708  else
     709    get_word ();
     710
     711  nameidx = get_index ();
     712  classidx = get_index ();
     713  ovlidx = get_index ();
     714  if (nameidx == 0)
     715      nameidx = classidx;               /* paranoia */
     716
     717  /* add it */
     718  if (!(num_segdefs % 64))
     719    segdefs = xrealloc (segdefs, sizeof(segdefs[0]) * (num_segdefs + 64));
     720  if (nameidx != 0 && nameidx < num_lnames)
     721    segdefs[num_segdefs].name = lnames[nameidx];
     722  else
     723    segdefs[num_segdefs].name = NULL;
     724  num_segdefs++;
     725}
     726
    378727
    379728
    380729static void process_omf (FILE *inp_file)
    381730{
    382   struct omf_rec rec;
    383 
     731  int               i;
     732  struct omf_rec    rec;
     733
     734  /* init */
    384735  new_mod = TRUE;
     736  lnames = xmalloc(sizeof(lnames[0])* 64);
     737  lnames[0] = NULL;
     738  num_lnames = 1;                       /* dummy entry */
     739  segdefs = xmalloc(sizeof(segdefs[0])* 64);
     740  memset(&segdefs[0], 0, sizeof(segdefs[0]));
     741  num_segdefs = 1;
     742
     743  /* read */
    385744  do
    386745    {
     
    402761          break;
    403762        case COMDEF:
    404           if (bss_flag)
     763          if (!legacy_mode || bss_flag)
    405764            omf_comdef ();
    406765          break;
     766        case LNAMES:
     767          omf_lnames ();
     768          break;
     769        case SEGDEF:
     770        case SEGDEF|REC32:
     771          omf_segdef ();
     772          break;
    407773        }
    408774    } while (rec.rec_type != MODEND && rec_type != (MODEND|REC32));
     775   
     776   /* cleanup (entry 0 isn't used) */
     777   for (i = 1; i < num_lnames; i++)
     778       free(lnames[i]);
     779   free(lnames);
     780   free(segdefs);
    409781}
    410782
     
    593965        case 'o':
    594966          if (optarg == NULL)
    595             ordinal = 1;
     967              ordinal = 1;
    596968          else
    597969            {
     
    601973                  || ordinal < 1 || ordinal > 65535)
    602974                usage ();
     975              ordinal_seq = 1;
    603976            }
    604977          break;
     
    609982          weak_flag = TRUE;
    610983          break;
     984        case 'l':
     985          legacy_mode = TRUE;
     986          break;
    611987        default:
    612988          error ("Invalid option");
     
    6251001    }
    6261002
     1003  if (!legacy_mode)
     1004    new_print(out_file, new_symgrps);
     1005
    6271006  if (fflush (out_file) != 0 || (out_file != stdout && fclose (out_file) != 0))
    6281007    error ("Write error");
Note: See TracChangeset for help on using the changeset viewer.