Hi,
this patch add a few features to the mach-o bfd back-end.
The function bfd_mach_o_fat_extract makes easier (and faster) to
extract
a member of a fat binary. Also if the bfd input is a thin one, and
corresponds
to the architecture requested, it is returned. So this function can
be
used to transparently handle fat binaries. Will be used in gdb.
Some well known sections and segments names are made shorter (no
LC_SEGMENT.
prefix). Made the output of objdump -h more readable.
The section that correspond to ".eh_frame" is now named ".eh_frame"
so that
it is recognized by gdb.
A few new mach-o load commands are now ignored (instead of
generating a
warning).
Tested by using gdb.
Tristan.
bfd/
2008-12-05 Tristan Gingold <gingold@adacore.com>
* mach-o.c (bfd_mach_o_make_bfd_section): Use the standard ELF name
.eh_frame for __TEXT.__eh_frame so that it is recognized by gdb.
Use shorter sections name for well known sections.
(bfd_mach_o_scan_read_dylinker): Only put dylinker name in the
section content.
(bfd_mach_o_scan_read_segment): Use shorter sections name for
well known segments.
(bfd_mach_o_scan_read_command): Ignore some new commands.
(bfd_mach_o_openr_next_archived_file): Use more descriptive names
for members filename.
(bfd_mach_o_fat_extract): New function to easily extract members
of a fat binary.
* mach-o.h (bfd_mach_o_load_command_type): Add new constants.
(bfd_mach_o_dylinker_command): Fix comment and reindent.
(bfd_mach_o_fat_extract): New prototype.
*** bfd/mach-o.c 6 Nov 2008 13:03:43 -0000 1.30
--- bfd/mach-o.c 5 Dec 2008 13:17:58 -0000
*************** bfd_mach_o_make_bfd_section (bfd *abfd,
*** 796,801 ****
--- 796,817 ----
if (strcmp (section->segname, "__DWARF") == 0
&& strncmp (section->sectname, "__", 2) == 0)
sprintf (sname, ".%s", section->sectname + 2);
+ else if (strcmp (section->segname, "__TEXT") == 0)
+ {
+ if (strcmp (section->sectname, "__eh_frame") == 0)
+ strcpy (sname, ".eh_frame");
+ else if (section->sectname[0])
+ sprintf (sname, "%s.%s", section->segname, section->sectname);
+ else
+ strcpy (sname, section->segname);
+ }
+ else if (strcmp (section->segname, "__DATA") == 0)
+ {
+ if (section->sectname[0])
+ sprintf (sname, "%s.%s", section->segname, section->sectname);
+ else
+ strcpy (sname, section->segname);
+ }
else
sprintf (sname, "%s.%s.%s", prefix, section->segname, section-
>sectname);
*************** bfd_mach_o_scan_read_dylinker (bfd *abfd
*** 1210,1217 ****
bfdsec->vma = 0;
bfdsec->lma = 0;
! bfdsec->size = command->len - 8;
! bfdsec->filepos = command->offset + 8;
bfdsec->alignment_power = 0;
cmd->section = bfdsec;
--- 1226,1233 ----
bfdsec->vma = 0;
bfdsec->lma = 0;
! bfdsec->size = command->len - nameoff;
! bfdsec->filepos = command->offset + nameoff;
bfdsec->alignment_power = 0;
cmd->section = bfdsec;
*************** bfd_mach_o_scan_read_segment (bfd *abfd,
*** 1584,1590 ****
sname = bfd_alloc (abfd, snamelen);
if (sname == NULL)
return -1;
! sprintf (sname, "%s.%s", prefix, seg->segname);
bfdsec = bfd_make_section_anyway (abfd, sname);
if (bfdsec == NULL)
--- 1600,1612 ----
sname = bfd_alloc (abfd, snamelen);
if (sname == NULL)
return -1;
! if (strcmp (seg->segname, "__TEXT") == 0
! || strcmp (seg->segname, "__DATA") == 0
! || strcmp (seg->segname, "__IMPORT") == 0
! || strcmp (seg->segname, "__LINKEDIT") == 0)
! strcpy (sname, seg->segname);
! else
! sprintf (sname, "%s.%s", prefix, seg->segname);
bfdsec = bfd_make_section_anyway (abfd, sname);
if (bfdsec == NULL)
*************** bfd_mach_o_scan_read_command (bfd *abfd,
*** 1708,1713 ****
--- 1730,1737 ----
return -1;
break;
case BFD_MACH_O_LC_CODE_SIGNATURE:
+ case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
+ case BFD_MACH_O_LC_REEXPORT_DYLIB:
break;
default:
fprintf (stderr, "unable to read unknown load command 0x%lx\n",
*************** bfd_mach_o_openr_next_archived_file (bfd
*** 2110,2119 ****
mach_o_fat_archentry *entry = NULL;
unsigned long i;
bfd *nbfd;
- const char *arch_name;
enum bfd_architecture arch_type;
unsigned long arch_subtype;
- char *s = NULL;
adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
BFD_ASSERT (adata != NULL);
--- 2134,2141 ----
*************** bfd_mach_o_openr_next_archived_file (bfd
*** 2153,2169 ****
bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
&arch_type, &arch_subtype);
! arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
! s = bfd_malloc (strlen (arch_name) + 1);
! if (s == NULL)
! return NULL;
! strcpy (s, arch_name);
! nbfd->filename = s;
nbfd->iostream = NULL;
return nbfd;
}
int
bfd_mach_o_lookup_section (bfd *abfd,
asection *section,
--- 2175,2264 ----
bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
&arch_type, &arch_subtype);
! /* Create the member filename.
! Use FILENAME:ARCH_NAME. */
! {
! char *s = NULL;
! const char *archive_name = lbasename (bfd_get_filename
(archive));
! size_t archive_name_len = strlen (archive_name);
! const char *arch_name;
!
! arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
! s = bfd_malloc (archive_name_len + 1 + strlen (arch_name) + 1);
! if (s == NULL)
! return NULL;
! memcpy (s, archive_name, archive_name_len);
! s[archive_name_len] = ':';
! strcpy (s + archive_name_len + 1, arch_name);
! nbfd->filename = s;
! }
nbfd->iostream = NULL;
+ bfd_set_arch_mach (nbfd, arch_type, arch_subtype);
return nbfd;
}
+ /* If ABFD format is FORMAT and architecture is ARCH, return it.
+ If ABFD is a fat image containing a member that corresponds to
FORMAT
+ and ARCH, returns it.
+ In other case, returns NULL.
+ This function allows transparent uses of fat images. */
+ bfd *
+ bfd_mach_o_fat_extract (bfd *abfd,
+ bfd_format format,
+ const bfd_arch_info_type *arch)
+ {
+ bfd *res;
+ mach_o_fat_data_struct *adata;
+ unsigned int i;
+
+ if (bfd_check_format (abfd, format))
+ {
+ if (bfd_get_arch_info (abfd) == arch)
+ return abfd;
+ return NULL;
+ }
+ if (!bfd_check_format (abfd, bfd_archive)
+ || abfd->xvec != &mach_o_fat_vec)
+ return NULL;
+
+ /* This is a Mach-O fat image. */
+ adata = (mach_o_fat_data_struct *) abfd->tdata.mach_o_fat_data;
+ BFD_ASSERT (adata != NULL);
+
+ for (i = 0; i < adata->nfat_arch; i++)
+ {
+ struct mach_o_fat_archentry *e = &adata->archentries[i];
+ enum bfd_architecture cpu_type;
+ unsigned long cpu_subtype;
+
+ bfd_mach_o_convert_architecture (e->cputype, e->cpusubtype,
+ &cpu_type, &cpu_subtype);
+ if (cpu_type != arch->arch || cpu_subtype != arch->mach)
+ continue;
+
+ /* The architecture is found. */
+ res = _bfd_new_bfd_contained_in (abfd);
+ if (res == NULL)
+ return NULL;
+
+ res->origin = e->offset;
+
+ res->filename = strdup (abfd->filename);
+ res->iostream = NULL;
+
+ if (bfd_check_format (res, format))
+ {
+ BFD_ASSERT (bfd_get_arch_info (res) == arch);
+ return res;
+ }
+ bfd_close (res);
+ return NULL;
+ }
+
+ return NULL;
+ }
+
int
bfd_mach_o_lookup_section (bfd *abfd,
asection *section,
Index: bfd/mach-o.h
===================================================================
RCS file: /cvs/src/src/bfd/mach-o.h,v
retrieving revision 1.11
diff -c -p -r1.11 mach-o.h
*** bfd/mach-o.h 6 Nov 2008 13:03:43 -0000 1.11
--- bfd/mach-o.h 5 Dec 2008 13:17:58 -0000
*************** typedef enum bfd_mach_o_load_command_typ
*** 105,111 ****
in a dylib. */
BFD_MACH_O_LC_UUID = 0x1b, /* 128-bit UUID of the
executable. */
BFD_MACH_O_LC_RPATH = 0x1c, /* Run path addiions. */
! BFD_MACH_O_LC_CODE_SIGNATURE = 0x1d /* Local of code signature.
*/
}
bfd_mach_o_load_command_type;
--- 105,115 ----
in a dylib. */
BFD_MACH_O_LC_UUID = 0x1b, /* 128-bit UUID of the
executable. */
BFD_MACH_O_LC_RPATH = 0x1c, /* Run path addiions. */
! BFD_MACH_O_LC_CODE_SIGNATURE = 0x1d, /* Local of code
signature. */
! BFD_MACH_O_LC_SEGMENT_SPLIT_INFO = 0x1e, /* Local of info to
split seg. */
! BFD_MACH_O_LC_REEXPORT_DYLIB = 0x1f, /* Load and re-export
lib. */
! BFD_MACH_O_LC_LAZY_LOAD_DYLIB = 0x20, /* Delay load of lib until
use. */
! BFD_MACH_O_LC_ENCRYPTION_INFO = 0x21 /* Encrypted segment
info. */
}
bfd_mach_o_load_command_type;
*************** bfd_mach_o_thread_command;
*** 458,467 ****
typedef struct bfd_mach_o_dylinker_command
{
! unsigned long cmd; /* LC_ID_DYLIB or
LC_LOAD_DYLIB. */
! unsigned long cmdsize; /* Includes pathname
string. */
! unsigned long name_offset; /* Offset to library's path
name. */
! unsigned long name_len; /* Offset to library's path
name. */
asection *section;
}
bfd_mach_o_dylinker_command;
--- 462,471 ----
typedef struct bfd_mach_o_dylinker_command
{
! unsigned long cmd; /* LC_ID_DYLINKER or
LC_LOAD_DYLINKER. */
! unsigned long cmdsize; /* Includes pathname string.
*/
! unsigned long name_offset; /* Offset to library's path
name. */
! unsigned long name_len; /* Offset to library's path
name. */
asection *section;
}
bfd_mach_o_dylinker_command;
*************** int bfd_mach_o_core_fetch
*** 555,560 ****
--- 559,565 ----
char * bfd_mach_o_core_file_failing_command (bfd *);
int bfd_mach_o_core_file_failing_signal (bfd *);
bfd_boolean bfd_mach_o_core_file_matches_executable_p (bfd
*, bfd *);
+ bfd *bfd_mach_o_fat_extract (bfd *, bfd_format , const
bfd_arch_info_type *);
extern const bfd_target mach_o_be_vec;
extern const bfd_target mach_o_le_vec;