1 /* od-avrelf.c -- dump information about an AVR elf object file.
2 Copyright (C) 2011-2024 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
)
86 section
= bfd_get_section_by_name (abfd
, ".note.gnu.avr.deviceinfo");
90 if (!bfd_malloc_and_get_section (abfd
, section
, &contents
))
96 *size
= bfd_section_size (section
);
97 return (char *) contents
;
101 elf32_avr_get_note_desc (bfd
*abfd
, char *contents
, bfd_size_type size
,
102 bfd_size_type
*descsz
)
104 Elf_External_Note
*xnp
= (Elf_External_Note
*) contents
;
105 Elf_Internal_Note in
;
107 if (offsetof (Elf_External_Note
, name
) > size
)
110 in
.type
= bfd_get_32 (abfd
, xnp
->type
);
111 in
.namesz
= bfd_get_32 (abfd
, xnp
->namesz
);
112 in
.namedata
= xnp
->name
;
113 if (in
.namesz
> contents
- in
.namedata
+ size
)
116 if (in
.namesz
!= 4 || strcmp (in
.namedata
, "AVR") != 0)
119 in
.descsz
= bfd_get_32 (abfd
, xnp
->descsz
);
120 in
.descdata
= in
.namedata
+ align_power (in
.namesz
, 2);
121 if (in
.descsz
< 6 * sizeof (uint32_t)
122 || in
.descdata
>= contents
+ size
123 || in
.descsz
> contents
- in
.descdata
+ size
)
126 /* If the note has a string table, ensure it is 0 terminated. */
127 if (in
.descsz
> 8 * sizeof (uint32_t))
128 in
.descdata
[in
.descsz
- 1] = 0;
135 elf32_avr_get_device_info (bfd
*abfd
, char *description
,
136 bfd_size_type desc_size
, deviceinfo
*device
)
138 if (description
== NULL
)
141 const bfd_size_type memory_sizes
= 6;
143 memcpy (device
, description
, memory_sizes
* sizeof (uint32_t));
144 desc_size
-= memory_sizes
* sizeof (uint32_t);
148 uint32_t *stroffset_table
= (uint32_t *) description
+ memory_sizes
;
149 bfd_size_type stroffset_table_size
= bfd_get_32 (abfd
, stroffset_table
);
151 /* If the only content is the size itself, there's nothing in the table */
152 if (stroffset_table_size
< 8)
154 if (desc_size
<= stroffset_table_size
)
156 desc_size
-= stroffset_table_size
;
158 /* First entry is the device name index. */
159 uint32_t device_name_index
= bfd_get_32 (abfd
, stroffset_table
+ 1);
160 if (device_name_index
>= desc_size
)
163 char *str_table
= (char *) stroffset_table
+ stroffset_table_size
;
164 device
->name
= str_table
+ device_name_index
;
168 elf32_avr_get_memory_usage (bfd
*abfd
,
169 bfd_size_type
*text_usage
,
170 bfd_size_type
*data_usage
,
171 bfd_size_type
*eeprom_usage
)
174 bfd_size_type avr_datasize
= 0;
175 bfd_size_type avr_textsize
= 0;
176 bfd_size_type avr_bsssize
= 0;
177 bfd_size_type bootloadersize
= 0;
178 bfd_size_type noinitsize
= 0;
179 bfd_size_type eepromsize
= 0;
183 if ((section
= bfd_get_section_by_name (abfd
, ".data")) != NULL
)
184 avr_datasize
= bfd_section_size (section
);
185 if ((section
= bfd_get_section_by_name (abfd
, ".text")) != NULL
)
186 avr_textsize
= bfd_section_size (section
);
187 if ((section
= bfd_get_section_by_name (abfd
, ".bss")) != NULL
)
188 avr_bsssize
= bfd_section_size (section
);
189 if ((section
= bfd_get_section_by_name (abfd
, ".bootloader")) != NULL
)
190 bootloadersize
= bfd_section_size (section
);
191 if ((section
= bfd_get_section_by_name (abfd
, ".noinit")) != NULL
)
192 noinitsize
= bfd_section_size (section
);
193 if ((section
= bfd_get_section_by_name (abfd
, ".eeprom")) != NULL
)
194 eepromsize
= bfd_section_size (section
);
196 /* PR 27285: Check for overflow. */
197 res
= avr_textsize
+ avr_datasize
;
198 if (res
< avr_textsize
|| res
< avr_datasize
)
200 fprintf (stderr
, _("Warning: textsize (%#lx) + datasize (%#lx) overflows size type\n"),
201 (long) avr_textsize
, (long) avr_datasize
);
202 res
= (bfd_size_type
) -1;
207 res2
= res
+ bootloadersize
;
208 if (res2
< bootloadersize
|| res2
< res
)
210 fprintf (stderr
, _("Warning: textsize (%#lx) + datasize (%#lx) + bootloadersize (%#lx) overflows size type\n"),
211 (long) avr_textsize
, (long) avr_datasize
, (long) bootloadersize
);
212 res2
= (bfd_size_type
) -1;
218 res
= avr_datasize
+ avr_bsssize
;
219 if (res
< avr_datasize
|| res
< avr_bsssize
)
221 fprintf (stderr
, _("Warning: datatsize (%#lx) + bssssize (%#lx) overflows size type\n"),
222 (long) avr_datasize
, (long) avr_bsssize
);
223 res
= (bfd_size_type
) -1;
229 res2
= res
+ noinitsize
;
230 if (res2
< res
|| res2
< noinitsize
)
232 fprintf (stderr
, _("Warning: datasize (%#lx) + bsssize (%#lx) + noinitsize (%#lx) overflows size type\n"),
233 (long) avr_datasize
, (long) avr_bsssize
, (long) noinitsize
);
234 res2
= (bfd_size_type
) -1;
240 *eeprom_usage
= eepromsize
;
244 elf32_avr_dump_mem_usage (bfd
*abfd
)
246 char *description
= NULL
;
247 bfd_size_type sec_size
, desc_size
;
249 deviceinfo device
= { 0, 0, 0, 0, 0, 0, NULL
};
250 device
.name
= "Unknown";
252 bfd_size_type data_usage
= 0;
253 bfd_size_type text_usage
= 0;
254 bfd_size_type eeprom_usage
= 0;
256 char *contents
= elf32_avr_get_note_section_contents (abfd
, &sec_size
);
258 if (contents
!= NULL
)
260 description
= elf32_avr_get_note_desc (abfd
, contents
, sec_size
,
262 elf32_avr_get_device_info (abfd
, description
, desc_size
, &device
);
265 elf32_avr_get_memory_usage (abfd
, &text_usage
, &data_usage
,
268 printf ("AVR Memory Usage\n"
270 "Device: %s\n\n", device
.name
);
273 printf ("Program:%8" PRIu64
" bytes", (uint64_t) text_usage
);
274 if (device
.flash_size
> 0)
275 printf (" (%2.1f%% Full)", (double) text_usage
/ device
.flash_size
* 100);
277 printf ("\n(.text + .data + .bootloader)\n\n");
280 printf ("Data: %8" PRIu64
" bytes", (uint64_t) data_usage
);
281 if (device
.ram_size
> 0)
282 printf (" (%2.1f%% Full)", (double) data_usage
/ device
.ram_size
* 100);
284 printf ("\n(.data + .bss + .noinit)\n\n");
287 if (eeprom_usage
> 0)
289 printf ("EEPROM: %8" PRIu64
" bytes", (uint64_t) eeprom_usage
);
290 if (device
.eeprom_size
> 0)
291 printf (" (%2.1f%% Full)",
292 (double) eeprom_usage
/ device
.eeprom_size
* 100);
294 printf ("\n(.eeprom)\n\n");
297 if (contents
!= NULL
)
303 elf32_avr_dump_avr_prop (bfd
*abfd
)
305 struct avr_property_record_list
*r_list
;
308 r_list
= avr_elf32_load_property_records (abfd
);
312 printf ("\nContents of `%s' section:\n\n", r_list
->section
->name
);
314 printf (" Version: %d\n", r_list
->version
);
315 printf (" Flags: %#x\n\n", r_list
->flags
);
317 for (i
= 0; i
< r_list
->record_count
; ++i
)
319 printf (" %d %s @ %s + %#08" PRIx64
" (%#08" PRIx64
")\n",
321 avr_elf32_property_record_name (&r_list
->records
[i
]),
322 r_list
->records
[i
].section
->name
,
323 (uint64_t) r_list
->records
[i
].offset
,
324 ((uint64_t) bfd_section_vma (r_list
->records
[i
].section
)
325 + r_list
->records
[i
].offset
));
326 switch (r_list
->records
[i
].type
)
329 /* Nothing else to print. */
331 case RECORD_ORG_AND_FILL
:
332 printf (" Fill: %#08lx\n",
333 r_list
->records
[i
].data
.org
.fill
);
336 printf (" Align: %#08lx\n",
337 r_list
->records
[i
].data
.align
.bytes
);
339 case RECORD_ALIGN_AND_FILL
:
340 printf (" Align: %#08lx, Fill: %#08lx\n",
341 r_list
->records
[i
].data
.align
.bytes
,
342 r_list
->records
[i
].data
.align
.fill
);
351 elf32_avr_dump (bfd
*abfd
)
353 if (options
[OPT_MEMUSAGE
].selected
)
354 elf32_avr_dump_mem_usage (abfd
);
355 if (options
[OPT_AVRPROP
].selected
)
356 elf32_avr_dump_avr_prop (abfd
);
359 const struct objdump_private_desc objdump_private_desc_elf32_avr
=