1 /* od-avrelf.c -- dump information about an AVR elf object file.
2 Copyright (C) 2011-2019 Free Software Foundation, Inc.
3 Written by Senthil Kumar Selvaraj, Atmel.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
26 #include "safe-ctype.h"
32 #include "elf/external.h"
33 #include "elf/internal.h"
34 #include "elf32-avr.h"
36 /* Index of the options in the options[] array. */
37 #define OPT_MEMUSAGE 0
40 /* List of actions. */
41 static struct objdump_private_option options
[] =
51 elf32_avr_help (FILE *stream
)
55 mem-usage Display memory usage\n\
56 avr-prop Display contents of .avr.prop section\n\
60 typedef struct tagDeviceInfo
66 uint32_t eeprom_start
;
72 /* Return TRUE if ABFD is handled. */
75 elf32_avr_filter (bfd
*abfd
)
77 return bfd_get_flavour (abfd
) == bfd_target_elf_flavour
;
81 elf32_avr_get_note_section_contents (bfd
*abfd
, bfd_size_type
*size
)
85 if ((section
= bfd_get_section_by_name (abfd
, ".note.gnu.avr.deviceinfo")) == NULL
)
88 *size
= bfd_get_section_size (section
);
89 char *contents
= (char *) xmalloc (*size
);
90 bfd_get_section_contents (abfd
, section
, contents
, 0, *size
);
95 static char* elf32_avr_get_note_desc (bfd
*abfd
, char *contents
,
98 Elf_External_Note
*xnp
= (Elf_External_Note
*) contents
;
101 if (offsetof (Elf_External_Note
, name
) > size
)
104 in
.type
= bfd_get_32 (abfd
, xnp
->type
);
105 in
.namesz
= bfd_get_32 (abfd
, xnp
->namesz
);
106 in
.namedata
= xnp
->name
;
107 if (in
.namesz
> contents
- in
.namedata
+ size
)
110 in
.descsz
= bfd_get_32 (abfd
, xnp
->descsz
);
111 in
.descdata
= in
.namedata
+ align_power (in
.namesz
, 2);
113 && (in
.descdata
>= contents
+ size
114 || in
.descsz
> contents
- in
.descdata
+ size
))
117 if (strcmp (in
.namedata
, "AVR") != 0)
124 elf32_avr_get_device_info (bfd
*abfd
, char *description
,
127 if (description
== NULL
)
130 const bfd_size_type memory_sizes
= 6;
132 memcpy (device
, description
, memory_sizes
* sizeof(uint32_t));
135 uint32_t *stroffset_table
= ((uint32_t *) description
) + memory_sizes
;
136 bfd_size_type stroffset_table_size
= bfd_get_32 (abfd
, stroffset_table
);
137 char *str_table
= ((char *) stroffset_table
) + stroffset_table_size
;
139 /* If the only content is the size itself, there's nothing in the table */
140 if (stroffset_table_size
== 4)
143 /* First entry is the device name index. */
144 uint32_t device_name_index
= bfd_get_32 (abfd
, stroffset_table
+ 1);
146 device
->name
= str_table
+ device_name_index
;
150 elf32_avr_get_memory_usage (bfd
*abfd
,
151 bfd_size_type
*text_usage
,
152 bfd_size_type
*data_usage
,
153 bfd_size_type
*eeprom_usage
)
156 bfd_size_type avr_datasize
= 0;
157 bfd_size_type avr_textsize
= 0;
158 bfd_size_type avr_bsssize
= 0;
159 bfd_size_type bootloadersize
= 0;
160 bfd_size_type noinitsize
= 0;
161 bfd_size_type eepromsize
= 0;
164 if ((section
= bfd_get_section_by_name (abfd
, ".data")) != NULL
)
165 avr_datasize
= bfd_section_size (abfd
, section
);
166 if ((section
= bfd_get_section_by_name (abfd
, ".text")) != NULL
)
167 avr_textsize
= bfd_section_size (abfd
, section
);
168 if ((section
= bfd_get_section_by_name (abfd
, ".bss")) != NULL
)
169 avr_bsssize
= bfd_section_size (abfd
, section
);
170 if ((section
= bfd_get_section_by_name (abfd
, ".bootloader")) != NULL
)
171 bootloadersize
= bfd_section_size (abfd
, section
);
172 if ((section
= bfd_get_section_by_name (abfd
, ".noinit")) != NULL
)
173 noinitsize
= bfd_section_size (abfd
, section
);
174 if ((section
= bfd_get_section_by_name (abfd
, ".eeprom")) != NULL
)
175 eepromsize
= bfd_section_size (abfd
, section
);
177 *text_usage
= avr_textsize
+ avr_datasize
+ bootloadersize
;
178 *data_usage
= avr_datasize
+ avr_bsssize
+ noinitsize
;
179 *eeprom_usage
= eepromsize
;
183 elf32_avr_dump_mem_usage (bfd
*abfd
)
185 char *description
= NULL
;
186 bfd_size_type note_section_size
= 0;
188 deviceinfo device
= { 0, 0, 0, 0, 0, 0, NULL
};
189 device
.name
= "Unknown";
191 bfd_size_type data_usage
= 0;
192 bfd_size_type text_usage
= 0;
193 bfd_size_type eeprom_usage
= 0;
195 char *contents
= elf32_avr_get_note_section_contents (abfd
,
198 if (contents
!= NULL
)
200 description
= elf32_avr_get_note_desc (abfd
, contents
, note_section_size
);
201 elf32_avr_get_device_info (abfd
, description
, &device
);
204 elf32_avr_get_memory_usage (abfd
, &text_usage
, &data_usage
,
207 printf ("AVR Memory Usage\n"
209 "Device: %s\n\n", device
.name
);
212 printf ("Program:%8ld bytes", text_usage
);
213 if (device
.flash_size
> 0)
214 printf (" (%2.1f%% Full)", ((float) text_usage
/ device
.flash_size
) * 100);
216 printf ("\n(.text + .data + .bootloader)\n\n");
219 printf ("Data: %8ld bytes", data_usage
);
220 if (device
.ram_size
> 0)
221 printf (" (%2.1f%% Full)", ((float) data_usage
/ device
.ram_size
) * 100);
223 printf ("\n(.data + .bss + .noinit)\n\n");
226 if (eeprom_usage
> 0)
228 printf ("EEPROM: %8ld bytes", eeprom_usage
);
229 if (device
.eeprom_size
> 0)
230 printf (" (%2.1f%% Full)", ((float) eeprom_usage
/ device
.eeprom_size
) * 100);
232 printf ("\n(.eeprom)\n\n");
235 if (contents
!= NULL
)
241 elf32_avr_dump_avr_prop (bfd
*abfd
)
243 struct avr_property_record_list
*r_list
;
246 r_list
= avr_elf32_load_property_records (abfd
);
250 printf ("\nContents of `%s' section:\n\n", r_list
->section
->name
);
252 printf (" Version: %d\n", r_list
->version
);
253 printf (" Flags: %#x\n\n", r_list
->flags
);
255 for (i
= 0; i
< r_list
->record_count
; ++i
)
257 printf (" %d %s @ %s + %#08lx (%#08lx)\n",
259 avr_elf32_property_record_name (&r_list
->records
[i
]),
260 r_list
->records
[i
].section
->name
,
261 r_list
->records
[i
].offset
,
262 (bfd_get_section_vma (abfd
, r_list
->records
[i
].section
)
263 + r_list
->records
[i
].offset
));
264 switch (r_list
->records
[i
].type
)
267 /* Nothing else to print. */
269 case RECORD_ORG_AND_FILL
:
270 printf (" Fill: %#08lx\n",
271 r_list
->records
[i
].data
.org
.fill
);
274 printf (" Align: %#08lx\n",
275 r_list
->records
[i
].data
.align
.bytes
);
277 case RECORD_ALIGN_AND_FILL
:
278 printf (" Align: %#08lx, Fill: %#08lx\n",
279 r_list
->records
[i
].data
.align
.bytes
,
280 r_list
->records
[i
].data
.align
.fill
);
289 elf32_avr_dump (bfd
*abfd
)
291 if (options
[OPT_MEMUSAGE
].selected
)
292 elf32_avr_dump_mem_usage (abfd
);
293 if (options
[OPT_AVRPROP
].selected
)
294 elf32_avr_dump_avr_prop (abfd
);
297 const struct objdump_private_desc objdump_private_desc_elf32_avr
=