/* Copyright (C) 1995-2025 Free Software Foundation, Inc.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
yacc generated parsers in ld. Note that these are only the variables
produced by yacc. If other parser generators (bison, byacc, etc) produce
additional global names that conflict at link time, then those parser
generators need to be fixed instead of adding those names to this list. */
/*****************************************************************************
API
*****************************************************************************/
static FILE *the_file;
static const char *def_filename;
static int linenumber;
static def_file *def;
static int saw_newline;
void
def_file_free (def_file *fdef)
{
int i;
unsigned int ui;
if (!fdef)
return;
free (fdef->name);
free (fdef->description);
if (fdef->section_defs)
{
for (i = 0; i < fdef->num_section_defs; i++)
{
free (fdef->section_defs[i].name);
free (fdef->section_defs[i].class);
}
free (fdef->section_defs);
}
for (i = 0; i < fdef->num_exports; i++)
{
if (fdef->exports[i].internal_name != fdef->exports[i].name)
free (fdef->exports[i].internal_name);
free (fdef->exports[i].name);
free (fdef->exports[i].its_name);
}
free (fdef->exports);
for (i = 0; i < fdef->num_imports; i++)
{
if (fdef->imports[i].internal_name != fdef->imports[i].name)
free (fdef->imports[i].internal_name);
free (fdef->imports[i].name);
free (fdef->imports[i].its_name);
}
free (fdef->imports);
while (fdef->modules)
{
def_file_module *m = fdef->modules;
fdef->modules = fdef->modules->next;
free (m);
}
while (fdef->aligncomms)
{
def_file_aligncomm *c = fdef->aligncomms;
/* Search the position of the identical element, or returns the position
of the next higher element. If last valid element is smaller, then MAX
is returned. The max parameter indicates the number of elements in the
array. On return, *is_ident indicates whether the returned array index
points at an element which is identical to the one searched for. */
static unsigned int
find_export_in_list (def_file_export *b, unsigned int max,
const char *ex_name, const char *in_name,
const char *its_name, int ord, bool *is_ident)
{
int e;
unsigned int l, r, p;
*is_ident = false;
if (!max)
return 0;
if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
{
if (!e)
*is_ident = true;
return 0;
}
if (max == 1)
return 1;
if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
return max;
else if (!e || max == 2)
{
if (!e)
*is_ident = true;
return max - 1;
}
l = 0; r = max - 1;
while (l < r)
{
p = (l + r) / 2;
e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
if (!e)
{
*is_ident = true;
return p;
}
else if (e < 0)
r = p - 1;
else if (e > 0)
l = p + 1;
}
if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
++l;
else if (!e)
*is_ident = true;
return l;
}
e = fdef->exports + pos;
/* If we're inserting in the middle of the array, we need to move the
following elements forward. */
if (pos != (unsigned)fdef->num_exports)
memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
/* Wipe the element for use as a new entry. */
memset (e, 0, sizeof (def_file_export));
e->name = xstrdup (external_name);
e->internal_name = xstrdup (internal_name);
e->its_name = (its_name ? xstrdup (its_name) : NULL);
e->ordinal = ordinal;
fdef->num_exports++;
return e;
}
/* Search the position of the identical element, or returns the position
of the next higher element. If last valid element is smaller, then MAX
is returned. The max parameter indicates the number of elements in the
array. On return, *is_ident indicates whether the returned array index
points at an element which is identical to the one searched for. */
static unsigned int
find_import_in_list (def_file_import *b, unsigned int max,
const char *ex_name, const char *in_name,
const char *module, int ord, bool *is_ident)
{
int e;
unsigned int l, r, p;
*is_ident = false;
if (!max)
return 0;
if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
{
if (!e)
*is_ident = true;
return 0;
}
if (max == 1)
return 1;
if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
return max;
else if (!e || max == 2)
{
if (!e)
*is_ident = true;
return max - 1;
}
l = 0; r = max - 1;
while (l < r)
{
p = (l + r) / 2;
e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
if (!e)
{
*is_ident = true;
return p;
}
else if (e < 0)
r = p - 1;
else if (e > 0)
l = p + 1;
}
if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
++l;
else if (!e)
*is_ident = true;
return l;
}
/* We need to avoid here duplicates. */
*is_dup = false;
pos = find_import_in_list (fdef->imports, fdef->num_imports,
name,
(!internal_name ? name : internal_name),
module, ordinal, is_dup);
if (*is_dup)
return fdef->imports + pos;
if ((unsigned)fdef->num_imports >= fdef->max_imports)
{
fdef->max_imports += SYMBOL_LIST_ARRAY_GROW;
fdef->imports = xrealloc (fdef->imports,
fdef->max_imports * sizeof (def_file_import));
}
i = fdef->imports + pos;
/* If we're inserting in the middle of the array, we need to move the
following elements forward. */
if (pos != (unsigned)fdef->num_imports)
memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
fdef->imports = xrealloc (fdef->imports,
fdef->max_imports * sizeof (def_file_import));
}
i = fdef->imports + pos;
/* If we're inserting in the middle of the array, we need to move the
following elements forward. */
if (pos != (unsigned)fdef->num_imports)
memmove (i + num_imports, i,
sizeof (def_file_import) * (fdef->num_imports - pos));
/* Search the position of the identical element, or returns the position
of the next higher element. If last valid element is smaller, then MAX
is returned. The max parameter indicates the number of elements in the
array. On return, *is_ident indicates whether the returned array index
points at an element which is identical to the one searched for. */
static unsigned int
find_exclude_in_list (def_file_exclude_symbol *b, unsigned int max,
const char *name, bool *is_ident)
{
int e;
unsigned int l, r, p;
*is_ident = false;
if (!max)
return 0;
if ((e = strcmp (b[0].symbol_name, name)) <= 0)
{
if (!e)
*is_ident = true;
return 0;
}
if (max == 1)
return 1;
if ((e = strcmp (b[max - 1].symbol_name, name)) > 0)
return max;
else if (!e || max == 2)
{
if (!e)
*is_ident = true;
return max - 1;
}
l = 0; r = max - 1;
while (l < r)
{
p = (l + r) / 2;
e = strcmp (b[p].symbol_name, name);
if (!e)
{
*is_ident = true;
return p;
}
else if (e < 0)
r = p - 1;
else if (e > 0)
l = p + 1;
}
if ((e = strcmp (b[l].symbol_name, name)) > 0)
++l;
else if (!e)
*is_ident = true;
return l;
}
e = fdef->exclude_symbols + pos;
/* If we're inserting in the middle of the array, we need to move the
following elements forward. */
if (pos != fdef->num_exclude_symbols)
memmove (&e[1], e, (sizeof (def_file_exclude_symbol) * (fdef->num_exclude_symbols - pos)));
/* Wipe the element for use as a new entry. */
memset (e, 0, sizeof (def_file_exclude_symbol));
e->symbol_name = xstrdup (name);
fdef->num_exclude_symbols++;
return e;
}
/* Scan forward until we encounter any of:
- the end of the buffer
- the start of a new option
- a newline separating options
- a NUL separating options. */
for (tend = (char *) (param + 1);
(tend < pend
&& !(ISSPACE (tend[-1]) && *tend == '-')
&& *tend != '\n' && *tend != 0);
tend++)
;
for (i = 0; diropts[i].param; i++)
{
len = strlen (diropts[i].param);
static void
def_image_name (const char *name, bfd_vma base, int is_dll)
{
/* If a LIBRARY or NAME statement is specified without a name, there is nothing
to do here. We retain the output filename specified on command line. */
if (*name)
{
const char* image_name = lbasename (name);
if (image_name != name)
einfo (_("%s:%d: Warning: path components stripped from %s, '%s'\n"),
def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
name);
free (def->name);
/* Append the default suffix, if none specified. */
if (strchr (image_name, '.') == 0)
{
const char * suffix = is_dll ? ".dll" : ".exe";
p = NULL;
c = def->aligncomms;
while (c != NULL)
{
int e = strcmp (c->symbol_name, str);
if (!e)
{
/* Not sure if we want to allow here duplicates with
different alignments, but for now we keep them. */
e = (int) c->alignment - align;
if (!e)
return;
}
if (e > 0)
break;
c = (p = c)->next;
}