From Eric Youngdale <eric@andante.jic.com>:

* elf-bfd.h (elf_symbol_type): Add version field.
	* elfcode.h (elf_slurp_symbol_table): Set version field.
	* elflink.h (elf_link_add_object_symbols): When creating an
 	indirect symbol for a default version symbol, set DEF_DYNAMIC if
 	appropriate.  Set up an indirection from the nondefault version of
	the symbol as well.
	(NAME(bfd_elf,size_dynamic_sections)): Call
	elf_link_assign_sym_version before checking whether there are any
	versions.  Always record the version name as a dynamic symbol.
	Initialize counters.
	(elf_link_assign_sym_version): After finding a version, see if a
	symbol should be forced to local scope.  Create a new version
	definition if appropriate.
	(elf_link_output_extsym): Correct indirect symbol handling.
	* elf.c (bfd_elf_print_symbol): Print version information.
	(bfd_section_from_shdr): Turn version sections into BFD sections.
	(elf_fake_sections): Only copy cverdefs and cverrefs into sh_info
	if sh_info is not already set.
	(_bfd_elf_copy_private_section_data): Copy sh_info for version
	sections.
	* elflink.c (_bfd_elf_link_record_dynamic_symbol): Tell
	_bfd_stringtab_add to copy the name into permanent memory if
	appropriate.
This commit is contained in:
Ian Lance Taylor 1997-03-10 04:43:42 +00:00
parent 998f2b67a9
commit d6bfcdb505
4 changed files with 344 additions and 56 deletions

View File

@ -1,3 +1,30 @@
Sun Mar 9 23:08:49 1997 Ian Lance Taylor <ian@cygnus.com>
From Eric Youngdale <eric@andante.jic.com>:
* elf-bfd.h (elf_symbol_type): Add version field.
* elfcode.h (elf_slurp_symbol_table): Set version field.
* elflink.h (elf_link_add_object_symbols): When creating an
indirect symbol for a default version symbol, set DEF_DYNAMIC if
appropriate. Set up an indirection from the nondefault version of
the symbol as well.
(NAME(bfd_elf,size_dynamic_sections)): Call
elf_link_assign_sym_version before checking whether there are any
versions. Always record the version name as a dynamic symbol.
Initialize counters.
(elf_link_assign_sym_version): After finding a version, see if a
symbol should be forced to local scope. Create a new version
definition if appropriate.
(elf_link_output_extsym): Correct indirect symbol handling.
* elf.c (bfd_elf_print_symbol): Print version information.
(bfd_section_from_shdr): Turn version sections into BFD sections.
(elf_fake_sections): Only copy cverdefs and cverrefs into sh_info
if sh_info is not already set.
(_bfd_elf_copy_private_section_data): Copy sh_info for version
sections.
* elflink.c (_bfd_elf_link_record_dynamic_symbol): Tell
_bfd_stringtab_add to copy the name into permanent memory if
appropriate.
Fri Mar 7 11:55:31 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
* elf64-alpha.c (alpha_elf_dynamic_symbol_p): Fully parenthesize.

View File

@ -1,5 +1,5 @@
/* BFD back-end data structures for ELF files.
Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@ -62,6 +62,12 @@ typedef struct
PTR any;
}
tc_data;
/* Version information. This is from an Elf_Internal_Versym
structure in a SHT_GNU_versym section. It is zero if there is no
version information. */
unsigned short version;
} elf_symbol_type;
/* ELF linker hash table entries. */
@ -107,6 +113,19 @@ struct elf_link_hash_entry
from the beginning of the section. */
struct elf_linker_section_pointers *linker_section_pointer;
/* Version information. */
union
{
/* This field is used for a symbol which is not defined in a
regular object. It points to the version information read in
from the dynamic object. */
Elf_Internal_Verdef *verdef;
/* This field is used for a symbol which is defined in a regular
object. It is set up in size_dynamic_sections. It points to
the version information we should write out for this symbol. */
struct bfd_elf_version_tree *vertree;
} verinfo;
/* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */
char type;
@ -114,7 +133,7 @@ struct elf_link_hash_entry
unsigned char other;
/* Some flags; legal values follow. */
unsigned char elf_link_hash_flags;
unsigned short elf_link_hash_flags;
/* Symbol is referenced by a non-shared object. */
#define ELF_LINK_HASH_REF_REGULAR 01
/* Symbol is defined by a non-shared object. */
@ -131,8 +150,8 @@ struct elf_link_hash_entry
#define ELF_LINK_HASH_NEEDS_PLT 0100
/* Symbol appears in a non-ELF input file. */
#define ELF_LINK_NON_ELF 0200
/* Note: If you add more flags, you must change the type of
elf_link_hash_flags. */
/* Symbol should be marked as hidden in the version information. */
#define ELF_LINK_HIDDEN 0400
};
/* ELF linker hash table. */
@ -572,8 +591,12 @@ struct elf_obj_tdata
Elf_Internal_Shdr strtab_hdr;
Elf_Internal_Shdr dynsymtab_hdr;
Elf_Internal_Shdr dynstrtab_hdr;
Elf_Internal_Shdr dynversym_hdr;
Elf_Internal_Shdr dynverref_hdr;
Elf_Internal_Shdr dynverdef_hdr;
unsigned int symtab_section, shstrtab_section;
unsigned int strtab_section, dynsymtab_section;
unsigned int dynversym_section, dynverdef_section, dynverref_section;
file_ptr next_file_pos;
void *prstatus; /* The raw /proc prstatus structure */
void *prpsinfo; /* The raw /proc prpsinfo structure */
@ -626,9 +649,26 @@ struct elf_obj_tdata
find_nearest_line. */
struct mips_elf_find_line *find_line_info;
/* An array of stub sections indexed by symbol number, used by the
MIPS ELF linker. FIXME: We should figure out some way to only
include this field for a MIPS ELF target. */
asection **local_stubs;
/* Used to determine if the e_flags field has been initialized */
boolean flags_init;
/* Number of symbol version definitions we are about to emit. */
int cverdefs;
/* Number of symbol version references we are about to emit. */
int cverrefs;
/* Symbol version definitions in external objects. */
Elf_Internal_Verdef *verdef;
/* Symbol version references to external objects. */
Elf_Internal_Verneed *verref;
/* Linker sections that we are interested in. */
struct elf_linker_section *linker_section[ (int)LINKER_SECTION_MAX ];
};
@ -639,6 +679,9 @@ struct elf_obj_tdata
#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr)
#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section)
#define elf_dynsymtab(bfd) (elf_tdata(bfd) -> dynsymtab_section)
#define elf_dynversym(bfd) (elf_tdata(bfd) -> dynversym_section)
#define elf_dynverdef(bfd) (elf_tdata(bfd) -> dynverdef_section)
#define elf_dynverref(bfd) (elf_tdata(bfd) -> dynverref_section)
#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals)
#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals)
#define elf_section_syms(bfd) (elf_tdata(bfd) -> section_syms)
@ -654,6 +697,27 @@ struct elf_obj_tdata
#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init)
#define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
extern void _bfd_elf_swap_verdef_in
PARAMS ((bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *));
extern void _bfd_elf_swap_verdef_out
PARAMS ((bfd *, const Elf_Internal_Verdef *, Elf_External_Verdef *));
extern void _bfd_elf_swap_verdaux_in
PARAMS ((bfd *, const Elf_External_Verdaux *, Elf_Internal_Verdaux *));
extern void _bfd_elf_swap_verdaux_out
PARAMS ((bfd *, const Elf_Internal_Verdaux *, Elf_External_Verdaux *));
extern void _bfd_elf_swap_verneed_in
PARAMS ((bfd *, const Elf_External_Verneed *, Elf_Internal_Verneed *));
extern void _bfd_elf_swap_verneed_out
PARAMS ((bfd *, const Elf_Internal_Verneed *, Elf_External_Verneed *));
extern void _bfd_elf_swap_vernaux_in
PARAMS ((bfd *, const Elf_External_Vernaux *, Elf_Internal_Vernaux *));
extern void _bfd_elf_swap_vernaux_out
PARAMS ((bfd *, const Elf_Internal_Vernaux *, Elf_External_Vernaux *));
extern void _bfd_elf_swap_versym_in
PARAMS ((bfd *, const Elf_External_Versym *, Elf_Internal_Versym *));
extern void _bfd_elf_swap_versym_out
PARAMS ((bfd *, const Elf_Internal_Versym *, Elf_External_Versym *));
extern int _bfd_elf_section_from_bfd_section PARAMS ((bfd *, asection *));
extern char *bfd_elf_string_from_elf_section
PARAMS ((bfd *, unsigned, unsigned));
@ -690,6 +754,7 @@ extern boolean _bfd_elf_link_hash_table_init
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *)));
extern boolean _bfd_elf_slurp_version_tables PARAMS ((bfd *));
extern boolean _bfd_elf_copy_private_symbol_data
PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
@ -712,6 +777,7 @@ extern long _bfd_elf_canonicalize_dynamic_reloc PARAMS ((bfd *, arelent **,
extern asymbol *_bfd_elf_make_empty_symbol PARAMS ((bfd *));
extern void _bfd_elf_get_symbol_info PARAMS ((bfd *, asymbol *,
symbol_info *));
extern boolean _bfd_elf_is_local_label_name PARAMS ((bfd *, const char *));
extern alent *_bfd_elf_get_lineno PARAMS ((bfd *, asymbol *));
extern boolean _bfd_elf_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
unsigned long));

110
bfd/elf.c
View File

@ -701,9 +701,10 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
}
/* Display ELF-specific fields of a symbol. */
void
bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
bfd *ignore_abfd;
bfd_elf_print_symbol (abfd, filep, symbol, how)
bfd *abfd;
PTR filep;
asymbol *symbol;
bfd_print_symbol_type how;
@ -733,11 +734,64 @@ bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
(bfd_is_com_section (symbol->section)
? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
: ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
/* If we have version information, print it. */
if (elf_tdata (abfd)->dynversym_section != 0
&& (elf_tdata (abfd)->dynverdef_section != 0
|| elf_tdata (abfd)->dynverref_section != 0))
{
unsigned int vernum;
const char *version_string;
vernum = ((elf_symbol_type *) symbol)->version & VERSYM_VERSION;
if (vernum == 0)
version_string = "";
else if (vernum == 1)
version_string = "Base";
else if (vernum < elf_tdata (abfd)->cverdefs)
version_string =
elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
else
{
Elf_Internal_Verneed *t;
version_string = "";
for (t = elf_tdata (abfd)->verref;
t != NULL;
t = t->vn_nextref)
{
Elf_Internal_Vernaux *a;
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
{
if (a->vna_other == vernum)
{
version_string = a->vna_nodename;
break;
}
}
}
}
if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0)
fprintf (file, " %-12s", version_string);
else
{
int i;
fprintf (file, " (%s)", version_string);
for (i = strlen (version_string) - 10; i > 0; --i)
putc (' ', file);
}
}
/* If the st_other field is not zero, print it. */
if (((elf_symbol_type *) symbol)->internal_elf_sym.st_other != 0)
fprintf (file, " 0x%02x",
((unsigned int)
((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
fprintf (file, " %s", symbol->name);
}
break;
@ -1098,16 +1152,19 @@ bfd_section_from_shdr (abfd, shindex)
case SHT_GNU_verdef:
elf_dynverdef (abfd) = shindex;
elf_tdata (abfd)->dynverdef_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
break;
case SHT_GNU_versym:
elf_dynversym (abfd) = shindex;
elf_tdata (abfd)->dynversym_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
break;
case SHT_GNU_verneed:
elf_dynverref (abfd) = shindex;
elf_tdata (abfd)->dynverref_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
break;
case SHT_SHLIB:
@ -1338,13 +1395,27 @@ elf_fake_sections (abfd, asect, failedptrarg)
{
this_hdr->sh_type = SHT_GNU_verdef;
this_hdr->sh_entsize = 0;
this_hdr->sh_info = elf_tdata (abfd)->cverdefs;
/* objcopy or strip will copy over sh_info, but may not set
cverdefs. The linker will set cverdefs, but sh_info will be
zero. */
if (this_hdr->sh_info == 0)
this_hdr->sh_info = elf_tdata (abfd)->cverdefs;
else
BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
}
else if (strcmp (asect->name, ".gnu.version_r") == 0)
{
this_hdr->sh_type = SHT_GNU_verneed;
this_hdr->sh_entsize = 0;
this_hdr->sh_info = elf_tdata (abfd)->cverrefs;
/* objcopy or strip will copy over sh_info, but may not set
cverrefs. The linker will set cverrefs, but sh_info will be
zero. */
if (this_hdr->sh_info == 0)
this_hdr->sh_info = elf_tdata (abfd)->cverrefs;
else
BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
}
else if ((asect->flags & SEC_ALLOC) != 0
&& (asect->flags & SEC_LOAD) != 0)
@ -3187,7 +3258,9 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
ohdr->sh_entsize = ihdr->sh_entsize;
if (ihdr->sh_type == SHT_SYMTAB
|| ihdr->sh_type == SHT_DYNSYM)
|| ihdr->sh_type == SHT_DYNSYM
|| ihdr->sh_type == SHT_GNU_verneed
|| ihdr->sh_type == SHT_GNU_verdef)
ohdr->sh_info = ihdr->sh_info;
return true;
@ -3831,17 +3904,34 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
bfd_symbol_info (symbol, ret);
}
/* Return whether a symbol name implies a local symbol. In ELF, local
symbols generally start with ``.L''. Most targets use this
function for the is_local_label_name entry point, but some override
it. */
/* Return whether a symbol name implies a local symbol. Most targets
use this function for the is_local_label_name entry point, but some
override it. */
boolean
_bfd_elf_is_local_label_name (abfd, name)
bfd *abfd;
const char *name;
{
return name[0] == '.' && name[1] == 'L';
/* Normal local symbols start with ``.L''. */
if (name[0] == '.' && name[1] == 'L')
return true;
/* At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
DWARF debugging symbols starting with ``..''. */
if (name[0] == '.' && name[1] == '.')
return true;
/* gcc will sometimes generate symbols beginning with ``_.L_'' when
emitting DWARF debugging output. I suspect this is actually a
small bug in gcc (it calls ASM_OUTPUT_LABEL when it should call
ASM_GENERATE_INTERNAL_LABEL, and this causes the leading
underscore to be emitted on some ELF targets). For ease of use,
we treat such symbols as local. */
if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
return true;
return false;
}
alent *

View File

@ -1075,7 +1075,41 @@ elf_link_add_object_symbols (abfd, info)
goto error_return;
if (hi->root.type == bfd_link_hash_indirect)
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
{
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
if (dynamic)
hi->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
/* We don't set DEF_REGULAR because we don't the
symbol to get exported even if we are
exporting all defined symbols. FIXME: What a
hack. */
/* FIXME: Do we need to copy any flags from H to
HI? */
}
/* We also need to define an indirection from the
nondefault version of the symbol. */
shortname = bfd_hash_allocate (&info->hash->table,
strlen (name));
if (shortname == NULL)
goto error_return;
strncpy (shortname, name, p - name);
strcpy (shortname + (p - name), p + 1);
hi = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT,
bfd_ind_section_ptr, (bfd_vma) 0, name, false,
collect, (struct bfd_link_hash_entry **) &hi)))
goto error_return;
if (hi->root.type == bfd_link_hash_indirect)
{
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
if (dynamic)
hi->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
}
}
}
@ -1823,30 +1857,35 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
size_t i;
size_t bucketcount = 0;
Elf_Internal_Sym isym;
struct elf_assign_sym_version_info sinfo;
/* Set up the version definition section. */
s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
BFD_ASSERT (s != NULL);
/* Attach all the symbols to their version information. This
may cause some symbols to be unexported. */
sinfo.output_bfd = output_bfd;
sinfo.info = info;
sinfo.verdefs = verdefs;
sinfo.export_dynamic = export_dynamic;
sinfo.removed_dynamic = false;
sinfo.failed = false;
elf_link_hash_traverse (elf_hash_table (info),
elf_link_assign_sym_version,
(PTR) &sinfo);
if (sinfo.failed)
return false;
/* We may have created additional version definitions if we are
just linking a regular application. */
verdefs = sinfo.verdefs;
if (verdefs == NULL)
{
struct elf_assign_sym_version_info sinfo;
asection **spp;
/* No version script was used. In this case, we just check
that there were no version overrides for any symbols. */
sinfo.output_bfd = output_bfd;
sinfo.info = info;
sinfo.verdefs = verdefs;
sinfo.removed_dynamic = false;
sinfo.export_dynamic = export_dynamic;
sinfo.failed = false;
elf_link_hash_traverse (elf_hash_table (info),
elf_link_assign_sym_version,
(PTR) &sinfo);
if (sinfo.failed)
return false;
/* Don't include this section in the output file. */
for (spp = &output_bfd->sections;
*spp != s->output_section;
@ -1857,7 +1896,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
}
else
{
struct elf_assign_sym_version_info sinfo;
unsigned int cdefs;
bfd_size_type size;
struct bfd_elf_version_tree *t;
@ -1865,20 +1903,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
Elf_Internal_Verdef def;
Elf_Internal_Verdaux defaux;
/* Attach all of the symbols to their version information.
This may cause some symbols to be unexported. */
sinfo.output_bfd = output_bfd;
sinfo.info = info;
sinfo.verdefs = verdefs;
sinfo.export_dynamic = export_dynamic;
sinfo.removed_dynamic = false;
sinfo.failed = false;
elf_link_hash_traverse (elf_hash_table (info),
elf_link_assign_sym_version,
(PTR) &sinfo);
if (sinfo.failed)
return false;
if (sinfo.removed_dynamic)
{
/* Some dynamic symbols were changed to be local
@ -1979,11 +2003,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
h->type = STT_OBJECT;
h->verinfo.vertree = t;
if (info->shared)
{
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
return false;
}
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
return false;
def.vd_version = VER_DEF_CURRENT;
def.vd_flags = 0;
@ -2075,6 +2096,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
bfd_byte *p;
/* Build the version definition section. */
size = 0;
crefs = 0;
for (t = elf_tdata (output_bfd)->verref;
t != NULL;
t = t->vn_nextref)
@ -2549,14 +2572,94 @@ elf_link_assign_sym_version (h, data)
{
h->verinfo.vertree = t;
t->used = true;
/* See if there is anything to force this symbol to
local scope. */
if (t->locals != NULL)
{
int len;
char *alc;
struct bfd_elf_version_expr *d;
len = p - h->root.root.string;
alc = bfd_alloc (sinfo->output_bfd, len);
if (alc == NULL)
return false;
strncpy (alc, h->root.root.string, len - 1);
alc[len - 1] = '\0';
if (alc[len - 2] == ELF_VER_CHR)
alc[len - 2] = '\0';
for (d = t->locals; d != NULL; d = d->next)
{
if ((d->match[0] == '*' && d->match[1] == '\0')
|| fnmatch (d->match, alc, 0) == 0)
{
if (h->dynindx != -1
&& info->shared
&& ! sinfo->export_dynamic
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_NEEDS_PLT) == 0)
{
sinfo->removed_dynamic = true;
h->dynindx = -1;
/* FIXME: The name of the symbol has
already been recorded in the dynamic
string table section. */
}
break;
}
}
bfd_release (sinfo->output_bfd, alc);
}
break;
}
}
if (t == NULL)
/* If we are building an application, we need to create a
version node for this version. */
if (t == NULL && ! info->shared)
{
/* We could not find the version. Return an error.
FIXME: Why? */
struct bfd_elf_version_tree **pp;
int version_index;
/* If we aren't going to export this symbol, we don't need
to worry about it. */
if (h->dynindx == -1)
return true;
t = ((struct bfd_elf_version_tree *)
bfd_alloc (sinfo->output_bfd, sizeof *t));
if (t == NULL)
{
sinfo->failed = true;
return false;
}
t->next = NULL;
t->name = p;
t->globals = NULL;
t->locals = NULL;
t->deps = NULL;
t->name_indx = (unsigned int) -1;
t->used = true;
version_index = 1;
for (pp = &sinfo->verdefs; *pp != NULL; pp = &(*pp)->next)
++version_index;
t->vernum = version_index;
*pp = t;
h->verinfo.vertree = t;
}
else if (t == NULL)
{
/* We could not find the version for a symbol when
generating a shared archive. Return an error. */
(*_bfd_error_handler)
("%s: invalid version %s", bfd_get_filename (sinfo->output_bfd),
h->root.root.string);
@ -3617,8 +3720,10 @@ elf_link_output_extsym (h, data)
to the decorated version of the name. For example, if the
symbol foo@@GNU_1.2 is the default, which should be used when
foo is used with no version, then we add an indirect symbol
foo which points to foo@@GNU_1.2. */
if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) != 0)
foo which points to foo@@GNU_1.2. We ignore these symbols,
since the indirected symbol is already in the hash table. If
the indirect symbol is non-ELF, fall through and output it. */
if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) == 0)
return true;
/* Fall through. */