* Makefile.in: Update dependencies.
	* dwarf2read.c: Include "addrmap.h"
	(struct dwarf2_cu): New fields RANGES_OFFSET and HAS_RANGES_OFFSET.
	(dwarf2_ranges_read): New prototype.
	(dwarf2_build_psymtabs_hard): Initialize and prepare PSYMTABS_ADDRMAP.
	Add discontiguous range to PSYMTABS_ADDRMAP by DWARF2_RANGES_READ on
	HAS_RANGES_OFFSET, otherwise add there the contiguous range.
	(dwarf2_ranges_read): New parameter RANGES_PST, update the function
	comment for it.  Add the found ranges to RANGES_PST.  New variable
	BASEADDR, initialize it the common way.
	(dwarf2_get_pc_bounds): Update the caller for the new parameter.
	(read_partial_die): `DW_AT_ranges' now only sets RANGES_OFFSET and
	HAS_RANGES_OFFSET for the later processing.
	* objfiles.h (struct objfile): New field PSYMTABS_ADDRMAP.
	* symtab.c: Include "addrmap.h"
	(find_pc_sect_psymtab): Support reading the field PSYMTABS_ADDRMAP.
	Move the psymtab locator into ...
	(find_pc_sect_psymtab_closer): ... a new function.

	gdb/testsuite/
	* gdb.dwarf2/dw2-ranges.S: Merge the secondary section with `.fini'.
	* gdb.dwarf2/dw2-ranges.exp: Compile also `dw2-ranges2.S' and
	`dw2-ranges3.S' and test also their MAIN2, FUNC2 and MAIN3 symbols.
	* gdb.dwarf2/dw2-ranges2.S, gdb.dwarf2/dw2-ranges3.S: New files.
This commit is contained in:
Jan Kratochvil 2008-05-04 17:27:01 +00:00
parent 85cbf3d35d
commit ff013f42f4
10 changed files with 314 additions and 80 deletions

View file

@ -6,6 +6,25 @@
DW_AT_ENTRY_PC. Set CU->HEADER.BASE_KNOWN and CU->HEADER.BASE_ADDRESS
from these variables if it was still unset.
* Makefile.in: Update dependencies.
* dwarf2read.c: Include "addrmap.h"
(struct dwarf2_cu): New fields RANGES_OFFSET and HAS_RANGES_OFFSET.
(dwarf2_ranges_read): New prototype.
(dwarf2_build_psymtabs_hard): Initialize and prepare PSYMTABS_ADDRMAP.
Add discontiguous range to PSYMTABS_ADDRMAP by DWARF2_RANGES_READ on
HAS_RANGES_OFFSET, otherwise add there the contiguous range.
(dwarf2_ranges_read): New parameter RANGES_PST, update the function
comment for it. Add the found ranges to RANGES_PST. New variable
BASEADDR, initialize it the common way.
(dwarf2_get_pc_bounds): Update the caller for the new parameter.
(read_partial_die): `DW_AT_ranges' now only sets RANGES_OFFSET and
HAS_RANGES_OFFSET for the later processing.
* objfiles.h (struct objfile): New field PSYMTABS_ADDRMAP.
* symtab.c: Include "addrmap.h"
(find_pc_sect_psymtab): Support reading the field PSYMTABS_ADDRMAP.
Move the psymtab locator into ...
(find_pc_sect_psymtab_closer): ... a new function.
2008-05-04 Ulrich Weigand <uweigand@de.ibm.com>
* arch-utils.c (gdbarch_update_p): Use default values for

View file

@ -2096,7 +2096,8 @@ dwarf2-frame.o: dwarf2-frame.c $(defs_h) $(dwarf2expr_h) $(elf_dwarf2_h) \
dwarf2loc.o: dwarf2loc.c $(defs_h) $(ui_out_h) $(value_h) $(frame_h) \
$(gdbcore_h) $(target_h) $(inferior_h) $(ax_h) $(ax_gdb_h) \
$(regcache_h) $(objfiles_h) $(exceptions_h) $(elf_dwarf2_h) \
$(dwarf2expr_h) $(dwarf2loc_h) $(gdb_string_h) $(gdb_assert_h)
$(dwarf2expr_h) $(dwarf2loc_h) $(gdb_string_h) $(gdb_assert_h) \
$(addrmap_h)
dwarf2read.o: dwarf2read.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
$(objfiles_h) $(elf_dwarf2_h) $(buildsym_h) $(demangle_h) \
$(expression_h) $(filenames_h) $(macrotab_h) $(language_h) \
@ -2915,7 +2916,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
$(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \
$(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \
$(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h) \
$(solist_h) $(p_lang_h)
$(solist_h) $(p_lang_h) $(addrmap_h)
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \

View file

@ -45,6 +45,7 @@
#include "hashtab.h"
#include "command.h"
#include "gdbcmd.h"
#include "addrmap.h"
#include <fcntl.h>
#include "gdb_string.h"
@ -303,6 +304,9 @@ struct dwarf2_cu
/* Hash table holding all the loaded partial DIEs. */
htab_t partial_dies;
/* `.debug_ranges' offset for this `DW_TAG_compile_unit' DIE. */
unsigned long ranges_offset;
/* Storage for things with the same lifetime as this read-in compilation
unit, including partial DIEs. */
struct obstack comp_unit_obstack;
@ -345,6 +349,9 @@ struct dwarf2_cu
DIEs for namespaces, we don't need to try to infer them
from mangled names. */
unsigned int has_namespace_info : 1;
/* Field `ranges_offset' is filled in; flag as the value may be zero. */
unsigned int has_ranges_offset : 1;
};
/* Persistent data held for a compilation unit, even when not
@ -894,6 +901,9 @@ static void read_func_scope (struct die_info *, struct dwarf2_cu *);
static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *, struct partial_symtab *);
static int dwarf2_get_pc_bounds (struct die_info *,
CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *);
@ -1472,6 +1482,9 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
create_all_comp_units (objfile);
objfile->psymtabs_addrmap = addrmap_create_mutable
(&objfile->objfile_obstack);
/* Since the objects we're extracting from .debug_info vary in
length, only the individual functions to extract them (like
read_comp_unit_head and load_partial_die) can really know whether
@ -1537,7 +1550,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
/* Allocate a new partial symbol table structure */
pst = start_psymtab_common (objfile, objfile->section_offsets,
comp_unit_die.name ? comp_unit_die.name : "",
comp_unit_die.lowpc,
/* TEXTLOW and TEXTHIGH are set below. */
0,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
@ -1570,6 +1584,15 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
this_cu->psymtab = pst;
/* Possibly set the default values of LOWPC and HIGHPC from
`DW_AT_ranges'. */
if (cu.has_ranges_offset)
{
if (dwarf2_ranges_read (cu.ranges_offset, &comp_unit_die.lowpc,
&comp_unit_die.highpc, &cu, pst))
comp_unit_die.has_pc_info = 1;
}
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
If not, there's no more debug_info for this comp unit. */
@ -1600,6 +1623,12 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
pst->textlow = comp_unit_die.lowpc + baseaddr;
pst->texthigh = comp_unit_die.highpc + baseaddr;
/* Store the contiguous range; `DW_AT_ranges' range is stored above. The
range can be also empty for CUs with no code. */
if (!cu.has_ranges_offset && pst->textlow < pst->texthigh)
addrmap_set_empty (objfile->psymtabs_addrmap, pst->textlow,
pst->texthigh - 1, pst);
pst->n_global_syms = objfile->global_psymbols.next -
(objfile->global_psymbols.list + pst->globals_offset);
pst->n_static_syms = objfile->static_psymbols.next -
@ -1623,6 +1652,10 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
do_cleanups (back_to_inner);
}
objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
&objfile->objfile_obstack);
do_cleanups (back_to);
}
@ -3143,11 +3176,13 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
}
/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
Return 1 if the attributes are present and valid, otherwise, return 0. */
Return 1 if the attributes are present and valid, otherwise, return 0.
If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */
static int
dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
CORE_ADDR *high_return, struct dwarf2_cu *cu)
CORE_ADDR *high_return, struct dwarf2_cu *cu,
struct partial_symtab *ranges_pst)
{
struct objfile *objfile = cu->objfile;
struct comp_unit_head *cu_header = &cu->header;
@ -3163,6 +3198,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
int low_set;
CORE_ADDR low = 0;
CORE_ADDR high = 0;
CORE_ADDR baseaddr;
found_base = cu_header->base_known;
base = cu_header->base_address;
@ -3190,6 +3226,9 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
low_set = 0;
if (ranges_pst != NULL)
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
while (1)
{
CORE_ADDR range_beginning, range_end;
@ -3229,6 +3268,11 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
range_beginning += base;
range_end += base;
if (ranges_pst != NULL && range_beginning < range_end)
addrmap_set_empty (objfile->psymtabs_addrmap,
range_beginning + baseaddr, range_end - 1 + baseaddr,
ranges_pst);
/* FIXME: This is recording everything as a low-high
segment of consecutive addresses. We should have a
data structure for discontiguous block ranges
@ -3293,7 +3337,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
{
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu))
if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu, NULL))
return 0;
/* Found discontinuous range of addresses. */
ret = -1;
@ -5880,9 +5924,11 @@ read_partial_die (struct partial_die_info *part_die,
}
break;
case DW_AT_ranges:
if (dwarf2_ranges_read (DW_UNSND (&attr), &part_die->lowpc,
&part_die->highpc, cu))
has_low_pc_attr = has_high_pc_attr = 1;
if (part_die->tag == DW_TAG_compile_unit)
{
cu->ranges_offset = DW_UNSND (&attr);
cu->has_ranges_offset = 1;
}
break;
case DW_AT_location:
/* Support the .debug_loc offsets */

View file

@ -220,6 +220,13 @@ struct objfile
struct partial_symtab *psymtabs;
/* Map addresses to the entries of PSYMTABS. It would be more efficient to
have a map per the whole process but ADDRMAP cannot selectively remove
its items during FREE_OBJFILE. This mapping is already present even for
PARTIAL_SYMTABs which still have no corresponding full SYMTABs read. */
struct addrmap *psymtabs_addrmap;
/* List of freed partial symtabs, available for re-use */
struct partial_symtab *free_psymtabs;

View file

@ -41,6 +41,7 @@
#include "objc-lang.h"
#include "ada-lang.h"
#include "p-lang.h"
#include "addrmap.h"
#include "hashtab.h"
@ -767,6 +768,83 @@ matching_bfd_sections (asection *first, asection *second)
return 0;
}
/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
We may find a different psymtab than PST. See FIND_PC_SECT_PSYMTAB. */
struct partial_symtab *
find_pc_sect_psymtab_closer (CORE_ADDR pc, asection *section,
struct partial_symtab *pst,
struct minimal_symbol *msymbol)
{
struct objfile *objfile = pst->objfile;
struct partial_symtab *tpst;
struct partial_symtab *best_pst = pst;
CORE_ADDR best_addr = pst->textlow;
/* An objfile that has its functions reordered might have
many partial symbol tables containing the PC, but
we want the partial symbol table that contains the
function containing the PC. */
if (!(objfile->flags & OBJF_REORDERED) &&
section == 0) /* can't validate section this way */
return pst;
if (msymbol == NULL)
return (pst);
/* The code range of partial symtabs sometimes overlap, so, in
the loop below, we need to check all partial symtabs and
find the one that fits better for the given PC address. We
select the partial symtab that contains a symbol whose
address is closest to the PC address. By closest we mean
that find_pc_sect_symbol returns the symbol with address
that is closest and still less than the given PC. */
for (tpst = pst; tpst != NULL; tpst = tpst->next)
{
if (pc >= tpst->textlow && pc < tpst->texthigh)
{
struct partial_symbol *p;
CORE_ADDR this_addr;
/* NOTE: This assumes that every psymbol has a
corresponding msymbol, which is not necessarily
true; the debug info might be much richer than the
object's symbol table. */
p = find_pc_sect_psymbol (tpst, pc, section);
if (p != NULL
&& SYMBOL_VALUE_ADDRESS (p)
== SYMBOL_VALUE_ADDRESS (msymbol))
return tpst;
/* Also accept the textlow value of a psymtab as a
"symbol", to provide some support for partial
symbol tables with line information but no debug
symbols (e.g. those produced by an assembler). */
if (p != NULL)
this_addr = SYMBOL_VALUE_ADDRESS (p);
else
this_addr = tpst->textlow;
/* Check whether it is closer than our current
BEST_ADDR. Since this symbol address is
necessarily lower or equal to PC, the symbol closer
to PC is the symbol which address is the highest.
This way we return the psymtab which contains such
best match symbol. This can help in cases where the
symbol information/debuginfo is not complete, like
for instance on IRIX6 with gcc, where no debug info
is emitted for statics. (See also the nodebug.exp
testcase.) */
if (this_addr > best_addr)
{
best_addr = this_addr;
best_pst = tpst;
}
}
}
return best_pst;
}
/* Find which partial symtab contains PC and SECTION. Return 0 if
none. We return the psymtab that contains a symbol whose address
exactly matches PC, or, if we cannot find an exact match, the
@ -774,7 +852,6 @@ matching_bfd_sections (asection *first, asection *second)
struct partial_symtab *
find_pc_sect_psymtab (CORE_ADDR pc, asection *section)
{
struct partial_symtab *pst;
struct objfile *objfile;
struct minimal_symbol *msymbol;
@ -790,79 +867,53 @@ find_pc_sect_psymtab (CORE_ADDR pc, asection *section)
|| msymbol->type == mst_file_bss))
return NULL;
ALL_PSYMTABS (objfile, pst)
{
if (pc >= pst->textlow && pc < pst->texthigh)
/* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
than the later used TEXTLOW/TEXTHIGH one. */
ALL_OBJFILES (objfile)
if (objfile->psymtabs_addrmap != NULL)
{
struct partial_symtab *tpst;
struct partial_symtab *best_pst = pst;
CORE_ADDR best_addr = pst->textlow;
struct partial_symtab *pst;
/* An objfile that has its functions reordered might have
many partial symbol tables containing the PC, but
we want the partial symbol table that contains the
function containing the PC. */
if (!(objfile->flags & OBJF_REORDERED) &&
section == 0) /* can't validate section this way */
return (pst);
if (msymbol == NULL)
return (pst);
/* The code range of partial symtabs sometimes overlap, so, in
the loop below, we need to check all partial symtabs and
find the one that fits better for the given PC address. We
select the partial symtab that contains a symbol whose
address is closest to the PC address. By closest we mean
that find_pc_sect_symbol returns the symbol with address
that is closest and still less than the given PC. */
for (tpst = pst; tpst != NULL; tpst = tpst->next)
pst = addrmap_find (objfile->psymtabs_addrmap, pc);
if (pst != NULL)
{
if (pc >= tpst->textlow && pc < tpst->texthigh)
{
struct partial_symbol *p;
CORE_ADDR this_addr;
/* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
PSYMTABS_ADDRMAP we used has already the best 1-byte
granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
overlap. */
/* NOTE: This assumes that every psymbol has a
corresponding msymbol, which is not necessarily
true; the debug info might be much richer than the
object's symbol table. */
p = find_pc_sect_psymbol (tpst, pc, section);
if (p != NULL
&& SYMBOL_VALUE_ADDRESS (p)
== SYMBOL_VALUE_ADDRESS (msymbol))
return (tpst);
/* Also accept the textlow value of a psymtab as a
"symbol", to provide some support for partial
symbol tables with line information but no debug
symbols (e.g. those produced by an assembler). */
if (p != NULL)
this_addr = SYMBOL_VALUE_ADDRESS (p);
else
this_addr = tpst->textlow;
/* Check whether it is closer than our current
BEST_ADDR. Since this symbol address is
necessarily lower or equal to PC, the symbol closer
to PC is the symbol which address is the highest.
This way we return the psymtab which contains such
best match symbol. This can help in cases where the
symbol information/debuginfo is not complete, like
for instance on IRIX6 with gcc, where no debug info
is emitted for statics. (See also the nodebug.exp
testcase.) */
if (this_addr > best_addr)
{
best_addr = this_addr;
best_pst = tpst;
}
}
return pst;
}
return (best_pst);
}
}
return (NULL);
/* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
which still have no corresponding full SYMTABs read. But it is not
present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
so far. */
ALL_OBJFILES (objfile)
{
struct partial_symtab *pst;
/* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
debug info type in single OBJFILE. */
ALL_OBJFILE_PSYMTABS (objfile, pst)
if (pc >= pst->textlow && pc < pst->texthigh)
{
struct partial_symtab *best_pst;
best_pst = find_pc_sect_psymtab_closer (pc, section, pst,
msymbol);
if (best_pst != NULL)
return best_pst;
}
}
return NULL;
}
/* Find which partial symtab contains PC. Return 0 if none.

View file

@ -1,3 +1,10 @@
2008-05-04 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.dwarf2/dw2-ranges.S: Merge the secondary section with `.fini'.
* gdb.dwarf2/dw2-ranges.exp: Compile also `dw2-ranges2.S' and
`dw2-ranges3.S' and test also their MAIN2, FUNC2 and MAIN3 symbols.
* gdb.dwarf2/dw2-ranges2.S, gdb.dwarf2/dw2-ranges3.S: New files.
2008-05-04 Vladimir Prus <vladimir@codesourcery.com>
* lib/mi-support.exp (mi_run_cmd): Allow for =thread-created

View file

@ -35,7 +35,10 @@ main: .int 0
.endfunc
.size main, . - main
.section .text.func, "ax", @progbits
/* `.fini' section is here to make sure `dw2-ranges.S'
vs. `dw2-ranges2.S' overlap their DW_AT_ranges with each other. */
.section .fini, "ax", @progbits
.globl func
.func func
func: .int 0

View file

@ -30,9 +30,23 @@ if {![istarget *-*-linux*]
set testfile "dw2-ranges"
set srcfile ${testfile}.S
set binfile ${objdir}/${subdir}/${testfile}.o
set srcfile2 ${testfile}2.S
set srcfile3 ${testfile}3.S
set objfile ${objdir}/${subdir}/${testfile}.o
set objfile2 ${objdir}/${subdir}/${testfile}2.o
set objfile3 ${objdir}/${subdir}/${testfile}3.o
set binfile ${objdir}/${subdir}/${testfile}
if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" object debug] != "" } {
if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {additional_flags=-gdwarf-2}] != "" } {
return -1
}
if {[gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${objfile2}" object {additional_flags=-gdwarf-2}] != "" } {
return -1
}
if {[gdb_compile "${srcdir}/${subdir}/${srcfile3}" "${objfile3}" object {additional_flags=-gstabs}] != "" } {
return -1
}
if {[gdb_compile "${objfile} ${objfile2} ${objfile3}" "${binfile}" executable {}] != "" } {
return -1
}
@ -46,4 +60,8 @@ gdb_load ${binfile}
# Wrong output:
# No line number information available for address 0x4
gdb_test "info line main" "Line \[0-9\]* of .* starts at address .* and ends at .*"
gdb_test "info line func" "Line \[0-9\]* of .* starts at address .* and ends at .*"
gdb_test "info line main2" "Line \[0-9\]* of .* starts at address .* and ends at .*"
gdb_test "info line func2" "Line \[0-9\]* of .* starts at address .* and ends at .*"
gdb_test "info line main3" "Line \[0-9\]* of .* starts at address .* and ends at .*"

View file

@ -0,0 +1,46 @@
/*
Copyright 2007 Free Software Foundation, Inc.
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, see <http://www.gnu.org/licenses/>.
*/
/* Despite the sections below will be adjacent the assembler has to produce
DW_AT_ranges as the linker could place both sections at arbitrary locations.
*/
/* Such directive is required by GAS for builds without `-g'. */
.file 1 "dw2-ranges2.S"
/* Without this directive GAS will not emit DWARF2 unless we provide an
instruction to assemble. We want to avoid any instructions to
remain architecture independent. */
.loc_mark_labels 1
.text
.globl main2
.func main2
main2: .int 0
.endfunc
.size main2, . - main2
/* `.fini' section is here to make sure `dw2-ranges.S'
vs. `dw2-ranges2.S' overlap their DW_AT_ranges with each other. */
.section .fini, "ax", @progbits
.globl func2
.func func2
func2: .int 0
.endfunc
.size func2, . - func2

View file

@ -0,0 +1,36 @@
/*
Copyright 2007, 2008 Free Software Foundation, Inc.
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, see <http://www.gnu.org/licenses/>.
*/
/* Despite the sections below will be adjacent the assembler has to produce
DW_AT_ranges as the linker could place both sections at arbitrary locations.
*/
/* Such directive is required by GAS for builds without `-g'. */
.file 1 "dw2-ranges3.S"
/* Without this directive GAS will not emit DWARF2 unless we provide an
instruction to assemble. We want to avoid any instructions to
remain architecture independent. */
.loc_mark_labels 1
.text
.globl main3
.func main3
main3: .int 0
.endfunc
.size main3, . - main3