avr/objdump: Support dumping .avr.prop section.
Add support to objdump for dumping the .avr.prop section in a structured way. binutils/ChangeLog: * od-elf32_avr.c: Add elf32-avr.h include. (OPT_AVRPROP): Define. (options[]): Add 'avr-prop' entry. (elf32_avr_help): Add avr-prop help text. (elf32_avr_dump_avr_prop): New function. (elf32_avr_dump): Add check for avr-prop. bfd/ChangeLog: * elf32-avr.h (struct avr_property_header): New strucure. (avr_elf32_load_property_records): Declare. (avr_elf32_property_record_name): Declare. * elf32-avr.c: Add bfd_stdint.h include. (retrieve_local_syms): New function. (get_elf_r_symndx_section): New function. (get_elf_r_symndx_offset): New function. (internal_reloc_compare): New function. (struct avr_find_section_data): New structure. (avr_is_section_for_address): New function. (avr_find_section_for_address): New function. (avr_elf32_load_records_from_section): New function. (avr_elf32_load_property_records): New function. (avr_elf32_property_record_name): New function. gas/testsuite/ChangeLog: * gas/avr/avr-prop-1.d: New file. * gas/avr/avr-prop-1.s: New file.
This commit is contained in:
parent
fdd410ac7a
commit
137c83d69f
@ -1,3 +1,20 @@
|
||||
2015-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* elf32-avr.h (struct avr_property_header): New strucure.
|
||||
(avr_elf32_load_property_records): Declare.
|
||||
(avr_elf32_property_record_name): Declare.
|
||||
* elf32-avr.c: Add bfd_stdint.h include.
|
||||
(retrieve_local_syms): New function.
|
||||
(get_elf_r_symndx_section): New function.
|
||||
(get_elf_r_symndx_offset): New function.
|
||||
(internal_reloc_compare): New function.
|
||||
(struct avr_find_section_data): New structure.
|
||||
(avr_is_section_for_address): New function.
|
||||
(avr_find_section_for_address): New function.
|
||||
(avr_elf32_load_records_from_section): New function.
|
||||
(avr_elf32_load_property_records): New function.
|
||||
(avr_elf32_property_record_name): New function.
|
||||
|
||||
2015-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* elf32-avr.h (AVR_PROPERTY_RECORD_SECTION_NAME): Define.
|
||||
|
439
bfd/elf32-avr.c
439
bfd/elf32-avr.c
@ -25,6 +25,7 @@
|
||||
#include "elf-bfd.h"
|
||||
#include "elf/avr.h"
|
||||
#include "elf32-avr.h"
|
||||
#include "bfd_stdint.h"
|
||||
|
||||
/* Enable debugging printout at stdout with this variable. */
|
||||
static bfd_boolean debug_relax = FALSE;
|
||||
@ -1935,6 +1936,118 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Elf_Internal_Sym *
|
||||
retrieve_local_syms (bfd *input_bfd)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
Elf_Internal_Sym *isymbuf;
|
||||
size_t locsymcount;
|
||||
|
||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||
locsymcount = symtab_hdr->sh_info;
|
||||
|
||||
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
if (isymbuf == NULL && locsymcount != 0)
|
||||
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Save the symbols for this input file so they won't be read again. */
|
||||
if (isymbuf && isymbuf != (Elf_Internal_Sym *) symtab_hdr->contents)
|
||||
symtab_hdr->contents = (unsigned char *) isymbuf;
|
||||
|
||||
return isymbuf;
|
||||
}
|
||||
|
||||
/* Get the input section for a given symbol index.
|
||||
If the symbol is:
|
||||
. a section symbol, return the section;
|
||||
. a common symbol, return the common section;
|
||||
. an undefined symbol, return the undefined section;
|
||||
. an indirect symbol, follow the links;
|
||||
. an absolute value, return the absolute section. */
|
||||
|
||||
static asection *
|
||||
get_elf_r_symndx_section (bfd *abfd, unsigned long r_symndx)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
asection *target_sec = NULL;
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
{
|
||||
Elf_Internal_Sym *isymbuf;
|
||||
unsigned int section_index;
|
||||
|
||||
isymbuf = retrieve_local_syms (abfd);
|
||||
section_index = isymbuf[r_symndx].st_shndx;
|
||||
|
||||
if (section_index == SHN_UNDEF)
|
||||
target_sec = bfd_und_section_ptr;
|
||||
else if (section_index == SHN_ABS)
|
||||
target_sec = bfd_abs_section_ptr;
|
||||
else if (section_index == SHN_COMMON)
|
||||
target_sec = bfd_com_section_ptr;
|
||||
else
|
||||
target_sec = bfd_section_from_elf_index (abfd, section_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long indx = r_symndx - symtab_hdr->sh_info;
|
||||
struct elf_link_hash_entry *h = elf_sym_hashes (abfd)[indx];
|
||||
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
switch (h->root.type)
|
||||
{
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
target_sec = h->root.u.def.section;
|
||||
break;
|
||||
case bfd_link_hash_common:
|
||||
target_sec = bfd_com_section_ptr;
|
||||
break;
|
||||
case bfd_link_hash_undefined:
|
||||
case bfd_link_hash_undefweak:
|
||||
target_sec = bfd_und_section_ptr;
|
||||
break;
|
||||
default: /* New indirect warning. */
|
||||
target_sec = bfd_und_section_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return target_sec;
|
||||
}
|
||||
|
||||
/* Get the section-relative offset for a symbol number. */
|
||||
|
||||
static bfd_vma
|
||||
get_elf_r_symndx_offset (bfd *abfd, unsigned long r_symndx)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
bfd_vma offset = 0;
|
||||
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
{
|
||||
Elf_Internal_Sym *isymbuf;
|
||||
isymbuf = retrieve_local_syms (abfd);
|
||||
offset = isymbuf[r_symndx].st_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long indx = r_symndx - symtab_hdr->sh_info;
|
||||
struct elf_link_hash_entry *h =
|
||||
elf_sym_hashes (abfd)[indx];
|
||||
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
offset = h->root.u.def.value;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* This function handles relaxing for the avr.
|
||||
Many important relaxing opportunities within functions are already
|
||||
realized by the compiler itself.
|
||||
@ -3347,6 +3460,332 @@ elf32_avr_build_stubs (struct bfd_link_info *info)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Callback used by QSORT to order relocations AP and BP. */
|
||||
|
||||
static int
|
||||
internal_reloc_compare (const void *ap, const void *bp)
|
||||
{
|
||||
const Elf_Internal_Rela *a = (const Elf_Internal_Rela *) ap;
|
||||
const Elf_Internal_Rela *b = (const Elf_Internal_Rela *) bp;
|
||||
|
||||
if (a->r_offset != b->r_offset)
|
||||
return (a->r_offset - b->r_offset);
|
||||
|
||||
/* We don't need to sort on these criteria for correctness,
|
||||
but enforcing a more strict ordering prevents unstable qsort
|
||||
from behaving differently with different implementations.
|
||||
Without the code below we get correct but different results
|
||||
on Solaris 2.7 and 2.8. We would like to always produce the
|
||||
same results no matter the host. */
|
||||
|
||||
if (a->r_info != b->r_info)
|
||||
return (a->r_info - b->r_info);
|
||||
|
||||
return (a->r_addend - b->r_addend);
|
||||
}
|
||||
|
||||
/* Return true if ADDRESS is within the vma range of SECTION from ABFD. */
|
||||
|
||||
static bfd_boolean
|
||||
avr_is_section_for_address (bfd *abfd, asection *section, bfd_vma address)
|
||||
{
|
||||
bfd_vma vma;
|
||||
bfd_size_type size;
|
||||
|
||||
vma = bfd_get_section_vma (abfd, section);
|
||||
if (address < vma)
|
||||
return FALSE;
|
||||
|
||||
size = section->size;
|
||||
if (address >= vma + size)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Data structure used by AVR_FIND_SECTION_FOR_ADDRESS. */
|
||||
|
||||
struct avr_find_section_data
|
||||
{
|
||||
/* The address we're looking for. */
|
||||
bfd_vma address;
|
||||
|
||||
/* The section we've found. */
|
||||
asection *section;
|
||||
};
|
||||
|
||||
/* Helper function to locate the section holding a certain virtual memory
|
||||
address. This is called via bfd_map_over_sections. The DATA is an
|
||||
instance of STRUCT AVR_FIND_SECTION_DATA, the address field of which
|
||||
has been set to the address to search for, and the section field has
|
||||
been set to NULL. If SECTION from ABFD contains ADDRESS then the
|
||||
section field in DATA will be set to SECTION. As an optimisation, if
|
||||
the section field is already non-null then this function does not
|
||||
perform any checks, and just returns. */
|
||||
|
||||
static void
|
||||
avr_find_section_for_address (bfd *abfd,
|
||||
asection *section, void *data)
|
||||
{
|
||||
struct avr_find_section_data *fs_data
|
||||
= (struct avr_find_section_data *) data;
|
||||
|
||||
/* Return if already found. */
|
||||
if (fs_data->section != NULL)
|
||||
return;
|
||||
|
||||
/* If this section isn't part of the addressable code content, skip it. */
|
||||
if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0
|
||||
&& (bfd_get_section_flags (abfd, section) & SEC_CODE) == 0)
|
||||
return;
|
||||
|
||||
if (avr_is_section_for_address (abfd, section, fs_data->address))
|
||||
fs_data->section = section;
|
||||
}
|
||||
|
||||
/* Load all of the property records from SEC, a section from ABFD. Return
|
||||
a STRUCT AVR_PROPERTY_RECORD_LIST containing all the records. The
|
||||
memory for the returned structure, and all of the records pointed too by
|
||||
the structure are allocated with a single call to malloc, so, only the
|
||||
pointer returned needs to be free'd. */
|
||||
|
||||
static struct avr_property_record_list *
|
||||
avr_elf32_load_records_from_section (bfd *abfd, asection *sec)
|
||||
{
|
||||
char *contents = NULL, *ptr;
|
||||
bfd_size_type size, mem_size;
|
||||
bfd_byte version, flags;
|
||||
uint16_t record_count, i;
|
||||
struct avr_property_record_list *r_list = NULL;
|
||||
Elf_Internal_Rela *internal_relocs = NULL, *rel, *rel_end;
|
||||
struct avr_find_section_data fs_data;
|
||||
|
||||
fs_data.section = NULL;
|
||||
|
||||
size = bfd_get_section_size (sec);
|
||||
contents = bfd_malloc (size);
|
||||
bfd_get_section_contents (abfd, sec, contents, 0, size);
|
||||
ptr = contents;
|
||||
|
||||
/* Load the relocations for the '.avr.prop' section if there are any, and
|
||||
sort them. */
|
||||
internal_relocs = (_bfd_elf_link_read_relocs
|
||||
(abfd, sec, NULL, NULL, FALSE));
|
||||
if (internal_relocs)
|
||||
qsort (internal_relocs, sec->reloc_count,
|
||||
sizeof (Elf_Internal_Rela), internal_reloc_compare);
|
||||
|
||||
/* There is a header at the start of the property record section SEC, the
|
||||
format of this header is:
|
||||
uint8_t : version number
|
||||
uint8_t : flags
|
||||
uint16_t : record counter
|
||||
*/
|
||||
|
||||
/* Check we have at least got a headers worth of bytes. */
|
||||
if (size < AVR_PROPERTY_SECTION_HEADER_SIZE)
|
||||
goto load_failed;
|
||||
|
||||
version = *((bfd_byte *) ptr);
|
||||
ptr++;
|
||||
flags = *((bfd_byte *) ptr);
|
||||
ptr++;
|
||||
record_count = *((uint16_t *) ptr);
|
||||
ptr+=2;
|
||||
BFD_ASSERT (ptr - contents == AVR_PROPERTY_SECTION_HEADER_SIZE);
|
||||
|
||||
/* Now allocate space for the list structure, and all of the list
|
||||
elements in a single block. */
|
||||
mem_size = sizeof (struct avr_property_record_list)
|
||||
+ sizeof (struct avr_property_record) * record_count;
|
||||
r_list = bfd_malloc (mem_size);
|
||||
if (r_list == NULL)
|
||||
goto load_failed;
|
||||
|
||||
r_list->version = version;
|
||||
r_list->flags = flags;
|
||||
r_list->section = sec;
|
||||
r_list->record_count = record_count;
|
||||
r_list->records = (struct avr_property_record *) (&r_list [1]);
|
||||
size -= AVR_PROPERTY_SECTION_HEADER_SIZE;
|
||||
|
||||
/* Check that we understand the version number. There is only one
|
||||
version number right now, anything else is an error. */
|
||||
if (r_list->version != AVR_PROPERTY_RECORDS_VERSION)
|
||||
goto load_failed;
|
||||
|
||||
rel = internal_relocs;
|
||||
rel_end = rel + sec->reloc_count;
|
||||
for (i = 0; i < record_count; ++i)
|
||||
{
|
||||
bfd_vma address;
|
||||
|
||||
/* Each entry is a 32-bit address, followed by a single byte type.
|
||||
After that is the type specific data. We must take care to
|
||||
ensure that we don't read beyond the end of the section data. */
|
||||
if (size < 5)
|
||||
goto load_failed;
|
||||
|
||||
r_list->records [i].section = NULL;
|
||||
r_list->records [i].offset = 0;
|
||||
|
||||
if (rel)
|
||||
{
|
||||
/* The offset of the address within the .avr.prop section. */
|
||||
size_t offset = ptr - contents;
|
||||
|
||||
while (rel < rel_end && rel->r_offset < offset)
|
||||
++rel;
|
||||
|
||||
if (rel == rel_end)
|
||||
rel = NULL;
|
||||
else if (rel->r_offset == offset)
|
||||
{
|
||||
/* Find section and section offset. */
|
||||
unsigned long r_symndx;
|
||||
|
||||
asection * rel_sec;
|
||||
bfd_vma sec_offset;
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
rel_sec = get_elf_r_symndx_section (abfd, r_symndx);
|
||||
sec_offset = get_elf_r_symndx_offset (abfd, r_symndx)
|
||||
+ rel->r_addend;
|
||||
|
||||
r_list->records [i].section = rel_sec;
|
||||
r_list->records [i].offset = sec_offset;
|
||||
}
|
||||
}
|
||||
|
||||
address = *((uint32_t *) ptr);
|
||||
ptr += 4;
|
||||
size -= 4;
|
||||
|
||||
if (r_list->records [i].section == NULL)
|
||||
{
|
||||
/* Try to find section and offset from address. */
|
||||
if (fs_data.section != NULL
|
||||
&& !avr_is_section_for_address (abfd, fs_data.section,
|
||||
address))
|
||||
fs_data.section = NULL;
|
||||
|
||||
if (fs_data.section == NULL)
|
||||
{
|
||||
fs_data.address = address;
|
||||
bfd_map_over_sections (abfd, avr_find_section_for_address,
|
||||
&fs_data);
|
||||
}
|
||||
|
||||
if (fs_data.section == NULL)
|
||||
{
|
||||
fprintf (stderr, "Failed to find matching section.\n");
|
||||
goto load_failed;
|
||||
}
|
||||
|
||||
r_list->records [i].section = fs_data.section;
|
||||
r_list->records [i].offset
|
||||
= address - bfd_get_section_vma (abfd, fs_data.section);
|
||||
}
|
||||
|
||||
r_list->records [i].type = *((bfd_byte *) ptr);
|
||||
ptr += 1;
|
||||
size -= 1;
|
||||
|
||||
switch (r_list->records [i].type)
|
||||
{
|
||||
case RECORD_ORG:
|
||||
/* Nothing else to load. */
|
||||
break;
|
||||
case RECORD_ORG_AND_FILL:
|
||||
/* Just a 4-byte fill to load. */
|
||||
if (size < 4)
|
||||
goto load_failed;
|
||||
r_list->records [i].data.org.fill = *((uint32_t *) ptr);
|
||||
ptr += 4;
|
||||
size -= 4;
|
||||
break;
|
||||
case RECORD_ALIGN:
|
||||
/* Just a 4-byte alignment to load. */
|
||||
if (size < 4)
|
||||
goto load_failed;
|
||||
r_list->records [i].data.align.bytes = *((uint32_t *) ptr);
|
||||
ptr += 4;
|
||||
size -= 4;
|
||||
/* Just initialise PRECEDING_DELETED field, this field is
|
||||
used during linker relaxation. */
|
||||
r_list->records [i].data.align.preceding_deleted = 0;
|
||||
break;
|
||||
case RECORD_ALIGN_AND_FILL:
|
||||
/* A 4-byte alignment, and a 4-byte fill to load. */
|
||||
if (size < 8)
|
||||
goto load_failed;
|
||||
r_list->records [i].data.align.bytes = *((uint32_t *) ptr);
|
||||
ptr += 4;
|
||||
r_list->records [i].data.align.fill = *((uint32_t *) ptr);
|
||||
ptr += 4;
|
||||
size -= 8;
|
||||
/* Just initialise PRECEDING_DELETED field, this field is
|
||||
used during linker relaxation. */
|
||||
r_list->records [i].data.align.preceding_deleted = 0;
|
||||
break;
|
||||
default:
|
||||
goto load_failed;
|
||||
}
|
||||
}
|
||||
|
||||
free (contents);
|
||||
free (internal_relocs);
|
||||
return r_list;
|
||||
|
||||
load_failed:
|
||||
free (internal_relocs);
|
||||
free (contents);
|
||||
free (r_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Load all of the property records from ABFD. See
|
||||
AVR_ELF32_LOAD_RECORDS_FROM_SECTION for details of the return value. */
|
||||
|
||||
struct avr_property_record_list *
|
||||
avr_elf32_load_property_records (bfd *abfd)
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
/* Find the '.avr.prop' section and load the contents into memory. */
|
||||
sec = bfd_get_section_by_name (abfd, AVR_PROPERTY_RECORD_SECTION_NAME);
|
||||
if (sec == NULL)
|
||||
return NULL;
|
||||
return avr_elf32_load_records_from_section (abfd, sec);
|
||||
}
|
||||
|
||||
const char *
|
||||
avr_elf32_property_record_name (struct avr_property_record *rec)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
switch (rec->type)
|
||||
{
|
||||
case RECORD_ORG:
|
||||
str = "ORG";
|
||||
break;
|
||||
case RECORD_ORG_AND_FILL:
|
||||
str = "ORG+FILL";
|
||||
break;
|
||||
case RECORD_ALIGN:
|
||||
str = "ALIGN";
|
||||
break;
|
||||
case RECORD_ALIGN_AND_FILL:
|
||||
str = "ALIGN+FILL";
|
||||
break;
|
||||
default:
|
||||
str = "unknown";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
#define ELF_ARCH bfd_arch_avr
|
||||
#define ELF_TARGET_ID AVR_ELF_DATA
|
||||
#define ELF_MACHINE_CODE EM_AVR
|
||||
|
@ -88,3 +88,35 @@ struct avr_property_record
|
||||
} align;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct avr_property_record_list
|
||||
{
|
||||
/* The version number tells us the structure of the property record data
|
||||
within the section. See AVR_PROPERTY_RECORDS_VERSION. */
|
||||
bfd_byte version;
|
||||
|
||||
/* The flags field is currently unused. This should be set to 0. */
|
||||
bfd_byte flags;
|
||||
|
||||
/* The number of property records. This is stored as a 2-byte value in
|
||||
the section contents. */
|
||||
unsigned long record_count;
|
||||
|
||||
/* The section from which the property records were loaded. This is the
|
||||
actual section containing the records, not the section(s) to which the
|
||||
records apply. */
|
||||
asection *section;
|
||||
|
||||
/* The actual property records. */
|
||||
struct avr_property_record *records;
|
||||
};
|
||||
|
||||
/* Load the property records from ABFD, return NULL if there are non
|
||||
found, otherwise return pointer to dynamically allocated memory. The
|
||||
memory for the header and all of the records are allocated in a single
|
||||
block, as such only the header needs to be freed. */
|
||||
|
||||
extern struct avr_property_record_list *avr_elf32_load_property_records (bfd *abfd);
|
||||
|
||||
/* Return a string that is the name of the property record pointed to by REC. */
|
||||
extern const char *avr_elf32_property_record_name (struct avr_property_record *rec);
|
||||
|
@ -1,3 +1,12 @@
|
||||
2015-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* od-elf32_avr.c: Add elf32-avr.h include.
|
||||
(OPT_AVRPROP): Define.
|
||||
(options[]): Add 'avr-prop' entry.
|
||||
(elf32_avr_help): Add avr-prop help text.
|
||||
(elf32_avr_dump_avr_prop): New function.
|
||||
(elf32_avr_dump): Add check for avr-prop.
|
||||
|
||||
2015-02-24 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* readelf.c (get_machine_flags): Remove deprecated V850 machine
|
||||
|
@ -31,14 +31,17 @@
|
||||
#include "bfd.h"
|
||||
#include "elf/external.h"
|
||||
#include "elf/internal.h"
|
||||
#include "elf32-avr.h"
|
||||
|
||||
/* Index of the options in the options[] array. */
|
||||
#define OPT_MEMUSAGE 0
|
||||
#define OPT_AVRPROP 1
|
||||
|
||||
/* List of actions. */
|
||||
static struct objdump_private_option options[] =
|
||||
{
|
||||
{ "mem-usage", 0 },
|
||||
{ "avr-prop", 0},
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@ -50,6 +53,7 @@ elf32_avr_help (FILE *stream)
|
||||
fprintf (stream, _("\
|
||||
For AVR ELF files:\n\
|
||||
mem-usage Display memory usage\n\
|
||||
avr-prop Display contents of .avr.prop section\n\
|
||||
"));
|
||||
}
|
||||
|
||||
@ -233,11 +237,61 @@ elf32_avr_dump_mem_usage (bfd *abfd)
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
elf32_avr_dump_avr_prop (bfd *abfd)
|
||||
{
|
||||
struct avr_property_record_list *r_list;
|
||||
unsigned int i;
|
||||
|
||||
r_list = avr_elf32_load_property_records (abfd);
|
||||
if (r_list == NULL)
|
||||
return;
|
||||
|
||||
printf ("\nContents of `%s' section:\n\n", r_list->section->name);
|
||||
|
||||
printf (" Version: %d\n", r_list->version);
|
||||
printf (" Flags: %#x\n\n", r_list->flags);
|
||||
|
||||
for (i = 0; i < r_list->record_count; ++i)
|
||||
{
|
||||
printf (" %d %s @ %s + %#08lx (%#08lx)\n",
|
||||
i,
|
||||
avr_elf32_property_record_name (&r_list->records [i]),
|
||||
r_list->records [i].section->name,
|
||||
r_list->records [i].offset,
|
||||
(bfd_get_section_vma (abfd, r_list->records [i].section)
|
||||
+ r_list->records [i].offset));
|
||||
switch (r_list->records [i].type)
|
||||
{
|
||||
case RECORD_ORG:
|
||||
/* Nothing else to print. */
|
||||
break;
|
||||
case RECORD_ORG_AND_FILL:
|
||||
printf (" Fill: %#08lx\n",
|
||||
r_list->records [i].data.org.fill);
|
||||
break;
|
||||
case RECORD_ALIGN:
|
||||
printf (" Align: %#08lx\n",
|
||||
r_list->records [i].data.align.bytes);
|
||||
break;
|
||||
case RECORD_ALIGN_AND_FILL:
|
||||
printf (" Align: %#08lx, Fill: %#08lx\n",
|
||||
r_list->records [i].data.align.bytes,
|
||||
r_list->records [i].data.org.fill);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (r_list);
|
||||
}
|
||||
|
||||
static void
|
||||
elf32_avr_dump (bfd *abfd)
|
||||
{
|
||||
if (options[OPT_MEMUSAGE].selected)
|
||||
elf32_avr_dump_mem_usage (abfd);
|
||||
if (options[OPT_AVRPROP].selected)
|
||||
elf32_avr_dump_avr_prop (abfd);
|
||||
}
|
||||
|
||||
const struct objdump_private_desc objdump_private_desc_elf32_avr =
|
||||
|
@ -1,3 +1,8 @@
|
||||
2015-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* gas/avr/avr-prop-1.d: New file.
|
||||
* gas/avr/avr-prop-1.s: New file.
|
||||
|
||||
2015-02-25 Kaz Kojima <kkojima@rr.iij4u.or.jp>
|
||||
Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
|
26
gas/testsuite/gas/avr/avr-prop-1.d
Normal file
26
gas/testsuite/gas/avr/avr-prop-1.d
Normal file
@ -0,0 +1,26 @@
|
||||
#name: AVR '.avr.prop' test 1
|
||||
#as: -mmcu=avrxmega2 -mlink-relax
|
||||
#objdump: -P avr-prop
|
||||
#source: avr-prop-1.s
|
||||
#target: avr-*-*
|
||||
|
||||
.*: file format elf32-avr
|
||||
|
||||
Contents of `\.avr\.prop' section:
|
||||
|
||||
Version: 1
|
||||
Flags: 0
|
||||
|
||||
0 ORG @ \.text\.1 \+ 0x000020 \(0x000020\)
|
||||
1 ORG @ \.text\.1 \+ 0x000044 \(0x000044\)
|
||||
2 ORG @ \.text\.2 \+ 0x000020 \(0x000020\)
|
||||
3 ALIGN @ \.text\.2 \+ 0x000020 \(0x000020\)
|
||||
Align: 0x000004
|
||||
4 ALIGN @ \.text\.2 \+ 0x000030 \(0x000030\)
|
||||
Align: 0x000004
|
||||
5 ORG @ \.text\.2 \+ 0x000200 \(0x000200\)
|
||||
6 ALIGN @ \.text\.2 \+ 0x000200 \(0x000200\)
|
||||
Align: 0x000004
|
||||
7 ALIGN @ \.text\.3 \+ 0x000100 \(0x000100\)
|
||||
Align: 0x000008
|
||||
|
29
gas/testsuite/gas/avr/avr-prop-1.s
Normal file
29
gas/testsuite/gas/avr/avr-prop-1.s
Normal file
@ -0,0 +1,29 @@
|
||||
.section ".text.1", "ax"
|
||||
.global _start
|
||||
_start:
|
||||
.org 0x20
|
||||
nop
|
||||
.org 0x44
|
||||
nop
|
||||
|
||||
|
||||
.section ".text.2", "ax"
|
||||
.global test2
|
||||
text2:
|
||||
.org 0x20
|
||||
nop
|
||||
.align 4
|
||||
nop
|
||||
.align 4
|
||||
nop
|
||||
.org 0x200
|
||||
nop
|
||||
|
||||
.section ".text.3", "ax"
|
||||
.global test3
|
||||
text3:
|
||||
.org 0x0
|
||||
nop
|
||||
nop
|
||||
.align 8
|
||||
nop
|
Loading…
Reference in New Issue
Block a user