diff options
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 5 | ||||
-rw-r--r-- | bfd/targets.c | 115 |
3 files changed, 126 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f261b68..fc6ed45 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2009-11-16 Kai Tietz <kai.tietz@onevision.com> + + * targets.c (bfd_get_target_info): New function. + (_bfd_find_arch_match): New function. + * bfd-in2.h: Regenerated. + 2009-11-12 Nick Clifton <nickc@redhat.com> * po/ru.po: Updates Russian translation. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index c9aa238..2cf3ba1 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5692,6 +5692,11 @@ bfd_boolean bfd_set_default_target (const char *name); const bfd_target *bfd_find_target (const char *target_name, bfd *abfd); +const bfd_target *bfd_get_target_info (const char *target_name, + bfd *abfd, + bfd_boolean *is_bigendian, + int *underscoring, + const char **def_target_arch); const char ** bfd_target_list (void); const bfd_target *bfd_search_for_target diff --git a/bfd/targets.c b/bfd/targets.c index 347c6cd..4062962 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -1428,6 +1428,121 @@ bfd_find_target (const char *target_name, bfd *abfd) return target; } +/* Helper function for bfd_get_target_info to determine the target's + architecture. This method handles bfd internal target names as + tuples and triplets. */ +static bfd_boolean +_bfd_find_arch_match (const char *tname, const char **arch, + const char **def_target_arch) +{ + if (!arch) + return FALSE; + + while (*arch != NULL) + { + const char *in_a = strstr (*arch, tname); + char end_ch = (in_a ? in_a[strlen (tname)] : 0); + + if (in_a && (in_a == *arch || in_a[-1] == ':') + && end_ch == 0) + { + *def_target_arch = *arch; + return TRUE; + } + arch++; + } + return FALSE; +} + +/* +FUNCTION + bfd_get_target_info +SYNOPSIS + const bfd_target *bfd_get_target_info (const char *target_name, + bfd *abfd, + bfd_boolean *is_bigendian, + int *underscoring, + const char **def_target_arch); +DESCRIPTION + Return a pointer to the transfer vector for the object target + named @var{target_name}. If @var{target_name} is <<NULL>>, + choose the one in the environment variable <<GNUTARGET>>; if + that is null or not defined, then choose the first entry in the + target list. Passing in the string "default" or setting the + environment variable to "default" will cause the first entry in + the target list to be returned, and "target_defaulted" will be + set in the BFD if @var{abfd} isn't <<NULL>>. This causes + <<bfd_check_format>> to loop over all the targets to find the + one that matches the file being read. + If @var{is_bigendian} is not <<NULL>>, then set this value to target's + endian mode. True for big-endian, FALSE for little-endian or for + invalid target. + If @var{underscoring} is not <<NULL>>, then set this value to target's + underscoring mode. Zero for none-underscoring, -1 for invalid target, + else the value of target vector's symbol underscoring. + If @var{def_target_arch} is not <<NULL>>, then set it to the architecture + string specified by the target_name. +*/ +const bfd_target * +bfd_get_target_info (const char *target_name, bfd *abfd, + bfd_boolean *is_bigendian, + int *underscoring, const char **def_target_arch) +{ + const bfd_target *target_vec; + + if (is_bigendian) + *is_bigendian = FALSE; + if (underscoring) + *underscoring = -1; + if (def_target_arch) + *def_target_arch = NULL; + target_vec = bfd_find_target (target_name, abfd); + if (! target_vec) + return NULL; + if (is_bigendian) + *is_bigendian = ((target_vec->byteorder == BFD_ENDIAN_BIG) ? TRUE + : FALSE); + if (underscoring) + *underscoring = ((int) target_vec->symbol_leading_char) & 0xff; + + if (def_target_arch) + { + const char *tname = target_vec->name; + const char **arches = bfd_arch_list (); + + if (arches && tname) + { + char *hyp = strchr (tname, '-'); + + if (hyp != NULL) + { + tname = ++hyp; + + /* Make sure we detect architecture names + for triplets like "pe-arm-wince-little". */ + if (!_bfd_find_arch_match (tname, arches, def_target_arch)) + { + char *new_tname = (char *) alloca (strlen (hyp) + 1); + strcpy (new_tname, hyp); + while ((hyp = strrchr (new_tname, '-')) != NULL) + { + *hyp = 0; + if (_bfd_find_arch_match (new_tname, arches, + def_target_arch)) + break; + } + } + } + else + _bfd_find_arch_match (tname, arches, def_target_arch); + } + + if (arches) + free (arches); + } + return target_vec; +} + /* FUNCTION bfd_target_list |