/* Mach-O support for BFD.
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009, 2010
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#define bfd_mach_o_object_p bfd_mach_o_gen_object_p
#define bfd_mach_o_core_p bfd_mach_o_gen_core_p
-#define bfd_mach_o_mkobject bfd_false
+#define bfd_mach_o_mkobject bfd_mach_o_gen_mkobject
#define FILE_ALIGN(off, algn) \
(((off) + ((file_ptr) 1 << (algn)) - 1) & ((file_ptr) -1 << (algn)))
{
const char *bfd_name;
const char *mach_o_name;
+ flagword flags;
};
static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] =
{
- { ".debug_frame", "__debug_frame" },
- { ".debug_info", "__debug_info" },
- { ".debug_abbrev", "__debug_abbrev" },
- { ".debug_aranges", "__debug_aranges" },
- { ".debug_macinfo", "__debug_macinfo" },
- { ".debug_line", "__debug_line" },
- { ".debug_loc", "__debug_loc" },
- { ".debug_pubnames", "__debug_pubnames" },
- { ".debug_pubtypes", "__debug_pubtypes" },
- { ".debug_str", "__debug_str" },
- { ".debug_ranges", "__debug_ranges" },
- { NULL, NULL}
+ { ".debug_frame", "__debug_frame", SEC_DEBUGGING },
+ { ".debug_info", "__debug_info", SEC_DEBUGGING },
+ { ".debug_abbrev", "__debug_abbrev", SEC_DEBUGGING },
+ { ".debug_aranges", "__debug_aranges", SEC_DEBUGGING },
+ { ".debug_macinfo", "__debug_macinfo", SEC_DEBUGGING },
+ { ".debug_line", "__debug_line", SEC_DEBUGGING },
+ { ".debug_loc", "__debug_loc", SEC_DEBUGGING },
+ { ".debug_pubnames", "__debug_pubnames", SEC_DEBUGGING },
+ { ".debug_pubtypes", "__debug_pubtypes", SEC_DEBUGGING },
+ { ".debug_str", "__debug_str", SEC_DEBUGGING },
+ { ".debug_ranges", "__debug_ranges", SEC_DEBUGGING },
+ { NULL, NULL, 0}
};
static const struct mach_o_section_name_xlat text_section_names_xlat[] =
{
- { ".text", "__text" },
- { ".const", "__const" },
- { ".cstring", "__cstring" },
- { ".eh_frame", "__eh_frame" },
- { NULL, NULL}
+ { ".text", "__text", SEC_CODE | SEC_LOAD },
+ { ".const", "__const", SEC_READONLY | SEC_DATA | SEC_LOAD },
+ { ".cstring", "__cstring", SEC_READONLY | SEC_DATA | SEC_LOAD },
+ { ".eh_frame", "__eh_frame", SEC_READONLY | SEC_LOAD },
+ { NULL, NULL, 0}
};
static const struct mach_o_section_name_xlat data_section_names_xlat[] =
{
- { ".data", "__data" },
- { ".bss", "__bss" },
- { NULL, NULL}
+ { ".data", "__data", SEC_DATA | SEC_LOAD },
+ { ".const_data", "__const", SEC_DATA | SEC_LOAD },
+ { ".dyld", "__dyld", SEC_DATA | SEC_LOAD },
+ { ".lazy_symbol_ptr", "__la_symbol_ptr", SEC_DATA | SEC_LOAD },
+ { ".non_lazy_symbol_ptr", "__nl_symbol_ptr", SEC_DATA | SEC_LOAD },
+ { ".bss", "__bss", SEC_NO_FLAGS },
+ { NULL, NULL, 0}
};
struct mach_o_segment_name_xlat
/* Mach-O to bfd names. */
-static char *
-bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, bfd_mach_o_section *section)
+static void
+bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, bfd_mach_o_section *section,
+ char **name, flagword *flags)
{
const struct mach_o_segment_name_xlat *seg;
char *res;
unsigned int len;
const char *pfx = "";
+ *name = NULL;
+ *flags = SEC_NO_FLAGS;
+
for (seg = segsec_names_xlat; seg->segname; seg++)
{
if (strcmp (seg->segname, section->segname) == 0)
res = bfd_alloc (abfd, len + 1);
if (res == NULL)
- return NULL;
+ return;
strcpy (res, sec->bfd_name);
- return res;
+ *name = res;
+ *flags = sec->flags;
+ return;
}
}
}
res = bfd_alloc (abfd, len);
if (res == NULL)
- return NULL;
+ return;
snprintf (res, len, "%s%s.%s", pfx, section->segname, section->sectname);
- return res;
+ *name = res;
}
/* Convert a bfd section name to a Mach-O segment + section name. */
res->addend = 0;
res->address = addr;
if (symnum & BFD_MACH_O_R_EXTERN)
- sym = syms + num;
+ {
+ sym = syms + num;
+ reloc.r_extern = 1;
+ }
else
{
BFD_ASSERT (num != 0);
BFD_ASSERT (num <= mdata->nsects);
sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
+ /* For a symbol defined in section S, the addend (stored in the
+ binary) contains the address of the section. To comply with
+ bfd conventio, substract the section address.
+ Use the address from the header, so that the user can modify
+ the vma of the section. */
+ res->addend = -mdata->sections[num - 1]->addr;
+ reloc.r_extern = 0;
}
res->sym_ptr_ptr = sym;
reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum);
char *sname;
flagword flags;
- sname = bfd_mach_o_convert_section_name_to_bfd (abfd, section);
+ bfd_mach_o_convert_section_name_to_bfd (abfd, section, &sname, &flags);
if (sname == NULL)
return NULL;
- if ((section->flags & BFD_MACH_O_S_ATTR_DEBUG)
- || !strcmp (section->segname, "__DWARF"))
+ if (flags == SEC_NO_FLAGS)
{
- /* Force flags for dwarf sections. This looks weird but dsym files
- have no flags for them and this is important for gdb. */
- flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
+ /* Try to guess flags. */
+ if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
+ flags = SEC_DEBUGGING;
+ else
+ {
+ flags = SEC_ALLOC;
+ if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
+ != BFD_MACH_O_S_ZEROFILL)
+ {
+ flags |= SEC_LOAD;
+ if (prot & BFD_MACH_O_PROT_EXECUTE)
+ flags |= SEC_CODE;
+ if (prot & BFD_MACH_O_PROT_WRITE)
+ flags |= SEC_DATA;
+ else if (prot & BFD_MACH_O_PROT_READ)
+ flags |= SEC_READONLY;
+ }
+ }
}
else
{
- flags = SEC_ALLOC;
- if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
- != BFD_MACH_O_S_ZEROFILL)
- {
- flags |= SEC_HAS_CONTENTS | SEC_LOAD;
- if (prot & BFD_MACH_O_PROT_EXECUTE)
- flags |= SEC_CODE;
- if (prot & BFD_MACH_O_PROT_WRITE)
- flags |= SEC_DATA;
- else if (prot & BFD_MACH_O_PROT_READ)
- flags |= SEC_READONLY;
- }
+ if ((flags & SEC_DEBUGGING) == 0)
+ flags |= SEC_ALLOC;
}
+
+ if (section->offset != 0)
+ flags |= SEC_HAS_CONTENTS;
if (section->nreloc != 0)
flags |= SEC_RELOC;
bfd_mach_o_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
{
bfd_mach_o_uuid_command *cmd = &command->command.uuid;
- asection *bfdsec;
- char *sname;
- static const char prefix[] = "LC_UUID";
BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
|| bfd_bread ((void *) cmd->uuid, 16, abfd) != 16)
return -1;
- sname = bfd_alloc (abfd, strlen (prefix) + 1);
- if (sname == NULL)
- return -1;
- strcpy (sname, prefix);
-
- bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
- if (bfdsec == NULL)
- return -1;
-
- bfdsec->vma = 0;
- bfdsec->lma = 0;
- bfdsec->size = command->len - 8;
- bfdsec->filepos = command->offset + 8;
- bfdsec->alignment_power = 0;
-
- cmd->section = bfdsec;
-
return 0;
}
return 0;
}
+bfd_boolean
+bfd_mach_o_set_arch_mach (bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long machine)
+{
+ bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
+
+ /* If this isn't the right architecture for this backend, and this
+ isn't the generic backend, fail. */
+ if (arch != bed->arch
+ && arch != bfd_arch_unknown
+ && bed->arch != bfd_arch_unknown)
+ return FALSE;
+
+ return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
int
bfd_mach_o_scan (bfd *abfd,
bfd_mach_o_header *header,
return TRUE;
}
+static bfd_boolean
+bfd_mach_o_gen_mkobject (bfd *abfd)
+{
+ bfd_mach_o_data_struct *mdata;
+
+ if (!bfd_mach_o_mkobject_init (abfd))
+ return FALSE;
+
+ mdata = bfd_mach_o_get_data (abfd);
+ mdata->header.magic = BFD_MACH_O_MH_MAGIC;
+ mdata->header.cputype = 0;
+ mdata->header.cpusubtype = 0;
+ mdata->header.byteorder = abfd->xvec->byteorder;
+ mdata->header.version = 1;
+
+ return TRUE;
+}
+
const bfd_target *
bfd_mach_o_header_p (bfd *abfd,
bfd_mach_o_filetype filetype,
#define TARGET_NAME mach_o_be_vec
#define TARGET_STRING "mach-o-be"
+#define TARGET_ARCHITECTURE bfd_arch_unknown
#define TARGET_BIG_ENDIAN 1
#define TARGET_ARCHIVE 0
#include "mach-o-target.c"
#undef TARGET_NAME
#undef TARGET_STRING
+#undef TARGET_ARCHITECTURE
#undef TARGET_BIG_ENDIAN
#undef TARGET_ARCHIVE
#define TARGET_NAME mach_o_le_vec
#define TARGET_STRING "mach-o-le"
+#define TARGET_ARCHITECTURE bfd_arch_unknown
#define TARGET_BIG_ENDIAN 0
#define TARGET_ARCHIVE 0
#undef TARGET_NAME
#undef TARGET_STRING
+#undef TARGET_ARCHITECTURE
#undef TARGET_BIG_ENDIAN
#undef TARGET_ARCHIVE
+/* Not yet handled: creating an archive. */
+#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive
+
+/* Not used. */
+#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr
+#define bfd_mach_o_write_ar_hdr _bfd_noarchive_write_ar_hdr
+#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap
+#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
+#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
+#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname
+#define bfd_mach_o_write_armap _bfd_noarchive_write_armap
+#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index
+#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt
+#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
+
#define TARGET_NAME mach_o_fat_vec
#define TARGET_STRING "mach-o-fat"
+#define TARGET_ARCHITECTURE bfd_arch_unknown
#define TARGET_BIG_ENDIAN 1
#define TARGET_ARCHIVE 1
#undef TARGET_NAME
#undef TARGET_STRING
+#undef TARGET_ARCHITECTURE
#undef TARGET_BIG_ENDIAN
#undef TARGET_ARCHIVE