summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@iki.fi>2009-03-17 18:52:33 +0200
committerLauri Leukkunen <lle@rahina.org>2009-03-23 01:37:48 +0200
commit0a405718da6da1d404c1b2fbcb350e9adc288a6f (patch)
tree22b271e7f373f834e6dd5f99fccad904e591c6b8
parent259e1fe6ead8c8723a6bc3a4035fc5ca822b6556 (diff)
x86_64 fix: now it is possible to run sb2 in 64-bit host
- Changed inpect_binary() to support 64-bit host binaries that are exec'd from 32-bit binary. - Initial shell is now invoked through host shell "trampoline" to get into the valid sb2 shell. - Corrected bug in sb2 that always generated ld_library_path_extras, even when it wasn't needed. Signed-off-by: Lauri Aarnio <Lauri.Aarnio@iki.fi>
-rw-r--r--preload/sb_exec.c201
-rwxr-xr-xutils/sb230
2 files changed, 127 insertions, 104 deletions
diff --git a/preload/sb_exec.c b/preload/sb_exec.c
index 6d739f2..727f1dd 100644
--- a/preload/sb_exec.c
+++ b/preload/sb_exec.c
@@ -123,30 +123,21 @@
# error Invalid __BYTE_ORDER
#endif
-#ifdef __i386__
-# define HOST_ELF_MACHINE EM_386
-#elif defined(__x86_64__)
-# define HOST_ELF_MACHINE EM_X86_64
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * We support exec'ing 64-bit programs from 32-bit programs
+ * as tools distribution might be 32-bit even in 64-bit machine.
+ */
+# define HOST_ELF_MACHINE_32 EM_386
+# define HOST_ELF_MACHINE_64 EM_X86_64
#elif defined(__ia64__)
-# define HOST_ELF_MACHINE EM_IA_64
+# define HOST_ELF_MACHINE_64 EM_IA_64
#elif defined(__powerpc__)
-# define HOST_ELF_MACHINE EM_PPC
+# define HOST_ELF_MACHINE_32 EM_PPC
#else
# error Unsupported host CPU architecture
#endif
-#ifndef PAGE_MASK
-# define PAGE_MASK sysconf(_SC_PAGE_SIZE)
-#endif
-
-#ifdef __x86_64__
-typedef Elf64_Ehdr Elf_Ehdr;
-typedef Elf64_Phdr Elf_Phdr;
-#else
-typedef Elf32_Ehdr Elf_Ehdr;
-typedef Elf32_Phdr Elf_Phdr;
-#endif
-
struct target_info {
char name[8];
uint16_t machine;
@@ -161,7 +152,8 @@ static const struct target_info target_table[] = {
{ "sh", EM_SH, ELFDATA2LSB, 1 },
};
-static int elf_hdr_match(Elf_Ehdr *ehdr, uint16_t match, int ei_data);
+static int elf_hdr_match(const char *region, uint16_t match, int ei_data);
+static enum binary_type inspect_elf_binary(const char *);
static int prepare_exec(const char *exec_fn_name,
const char *orig_file, int file_has_been_mapped,
@@ -263,8 +255,13 @@ char **split_to_tokens(char *str)
return tokens;
}
-static int elf_hdr_match(Elf_Ehdr *ehdr, uint16_t match, int ei_data)
+static int elf_hdr_match(const char *region, uint16_t match, int ei_data)
{
+ /*
+ * It is OK to use Elf32_Ehdr here because fields accessed
+ * in this function are same in both 64-bit and 32-bit ELF formats.
+ */
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)region;
int swap;
if (ehdr->e_ident[EI_DATA] != ei_data)
@@ -285,21 +282,65 @@ static int elf_hdr_match(Elf_Ehdr *ehdr, uint16_t match, int ei_data)
return 0;
}
+static enum binary_type inspect_elf_binary(const char *region)
+{
+ assert(region != NULL);
+
+ /* check for hashbang */
+ if (region[EI_MAG0] == '#' && region[EI_MAG1] == '!')
+ return (BIN_HASHBANG);
+
+ /*
+ * We go through ELF program headers one by one and check
+ * whether there is interpreter (PT_INTERP) section.
+ * In that case this is dynamically linked, otherwise
+ * it is statically linked.
+ */
+#ifdef HOST_ELF_MACHINE_32
+ if (elf_hdr_match(region, HOST_ELF_MACHINE_32, HOST_ELF_DATA)) {
+ Elf32_Ehdr *eh = (Elf32_Ehdr *)region;
+ Elf32_Phdr *ph;
+ size_t ph_entsize = eh->e_phentsize;
+ int i;
+
+ for (i = 0; i < eh->e_phnum; i++) {
+ ph = (Elf32_Phdr *)
+ (region + eh->e_phoff + (i * ph_entsize));
+ if (ph->p_type == PT_INTERP)
+ return (BIN_HOST_DYNAMIC);
+ }
+ return (BIN_HOST_STATIC);
+ }
+#endif
+#ifdef HOST_ELF_MACHINE_64
+ if (elf_hdr_match(region, HOST_ELF_MACHINE_64, HOST_ELF_DATA)) {
+ Elf64_Ehdr *eh = (Elf64_Ehdr *)region;
+ Elf64_Phdr *ph;
+ size_t ph_entsize = eh->e_phentsize;
+ int i;
+
+ for (i = 0; i < eh->e_phnum; i++) {
+ ph = (Elf64_Phdr *)
+ (region + eh->e_phoff + (i * ph_entsize));
+ if (ph->p_type == PT_INTERP)
+ return (BIN_HOST_DYNAMIC);
+ }
+ return (BIN_HOST_STATIC);
+ }
+#endif
+ /* could not identify as host binary */
+ return (BIN_UNKNOWN);
+}
+
static enum binary_type inspect_binary(const char *filename)
{
+ static char *target_cpu = NULL;
enum binary_type retval;
- int fd, phnum, j;
+ int fd, j;
struct stat status;
char *region;
- unsigned int ph_base, ph_frag, ei_data;
+ unsigned int ei_data;
uint16_t e_machine;
-#ifdef __x86_64__
- int64_t reloc0;
-#else
- int reloc0;
-#endif
- Elf_Ehdr *ehdr;
- Elf_Phdr *phdr;
retval = BIN_NONE; /* assume it doesn't exist, until proven otherwise */
if (access_nomap_nolog(filename, X_OK) < 0) {
@@ -394,83 +435,59 @@ static enum binary_type inspect_binary(const char *filename)
goto _out_close;
}
- /* check for hashbang */
-
- if (region[0] == '#' && region[1] == '!') {
- retval = BIN_HASHBANG;
+ retval = inspect_elf_binary(region);
+ switch (retval) {
+ case BIN_HASHBANG:
+ case BIN_HOST_STATIC:
+ case BIN_HOST_DYNAMIC:
+ /* host binary, lets go out of here */
goto _out_munmap;
- }
-
- ehdr = (Elf_Ehdr *) region;
-
-#ifdef __x86_64__
- if (elf_hdr_match(ehdr, EM_386, HOST_ELF_DATA) ||
- elf_hdr_match(ehdr, EM_X86_64, HOST_ELF_DATA)) {
-#else
- if (elf_hdr_match(ehdr, HOST_ELF_MACHINE, HOST_ELF_DATA)) {
-#endif
- retval = BIN_HOST_STATIC;
- phnum = ehdr->e_phnum;
- reloc0 = ~0;
- ph_base = ehdr->e_phoff & PAGE_MASK;
- ph_frag = ehdr->e_phoff - ph_base;
-
- phdr = (Elf_Phdr *) (region + ph_base + ph_frag);
-
- for (j = phnum; --j >= 0; ++phdr)
- if (PT_LOAD == phdr->p_type && ~0 == reloc0)
- reloc0 = phdr->p_vaddr - phdr->p_offset;
-
- phdr -= phnum;
-
- for (j = phnum; --j >= 0; ++phdr) {
- if (PT_DYNAMIC != phdr->p_type)
- continue;
-
- retval = BIN_HOST_DYNAMIC;
- }
- } else {
- static char *target_cpu = NULL;
-
- if (!target_cpu) {
- target_cpu = sb2__read_string_variable_from_lua__(
- "sbox_cpu");
+ default:
+ break;
+ }
- if (!target_cpu)
- target_cpu = "arm";
- }
+ /*
+ * Target binary. Find out whether it is supported
+ * by scratchbox2.
+ */
+ if (!target_cpu) {
+ target_cpu = sb2__read_string_variable_from_lua__(
+ "sbox_cpu");
- ei_data = ELFDATANONE;
- e_machine = EM_NONE;
+ if (!target_cpu)
+ target_cpu = "arm";
+ }
- for (j = 0; (size_t) j < ARRAY_SIZE(target_table); j++) {
- const struct target_info *ti = &target_table[j];
+ ei_data = ELFDATANONE;
+ e_machine = EM_NONE;
- if (strncmp(target_cpu, ti->name, strlen(ti->name)))
- continue;
+ for (j = 0; (size_t) j < ARRAY_SIZE(target_table); j++) {
+ const struct target_info *ti = &target_table[j];
- ei_data = ti->default_byteorder;
- e_machine = ti->machine;
+ if (strncmp(target_cpu, ti->name, strlen(ti->name)))
+ continue;
- if (ti->multi_byteorder &&
- strlen(target_cpu) >= strlen(ti->name) + 2) {
- size_t len = strlen(target_cpu);
- const char *tail = target_cpu + len - 2;
+ ei_data = ti->default_byteorder;
+ e_machine = ti->machine;
- if (strcmp(tail, "eb") == 0)
- ei_data = ELFDATA2MSB;
- else if (strcmp(tail, "el") == 0)
- ei_data = ELFDATA2LSB;
- }
+ if (ti->multi_byteorder &&
+ strlen(target_cpu) >= strlen(ti->name) + 2) {
+ size_t len = strlen(target_cpu);
+ const char *tail = target_cpu + len - 2;
- break;
+ if (strcmp(tail, "eb") == 0)
+ ei_data = ELFDATA2MSB;
+ else if (strcmp(tail, "el") == 0)
+ ei_data = ELFDATA2LSB;
}
- if (elf_hdr_match(ehdr, e_machine, ei_data))
- retval = BIN_TARGET;
+ break;
}
+ if (elf_hdr_match(region, e_machine, ei_data))
+ retval = BIN_TARGET;
+
_out_munmap:
munmap(region, status.st_size);
_out_close:
diff --git a/utils/sb2 b/utils/sb2
index f1a6dbe..48ab9f7 100755
--- a/utils/sb2
+++ b/utils/sb2
@@ -726,7 +726,7 @@ END
$HOME/.scratchbox2/$tools_basename/locales \
conf_tools_locale_path
- if [ ld_so_found != "yes" ]; then
+ if [ $ld_so_found != "yes" ]; then
# ld.so from tools can not be used. Add tools' shared
# library locations to the normal LD_LIBRARY_PATH;
# this is risky but the best what we can do now
@@ -1169,12 +1169,7 @@ fi
# set the initial binary name for the mapping engine
export __SB2_BINARYNAME="bash"
-
-if [ -n "$SBOX_TOOLS_ROOT" ]; then
- SHELL=$SBOX_TOOLS_ROOT/bin/bash
-else
- SHELL=/bin/bash
-fi
+SHELL=/bin/bash
# Final addition to LD_LIBRARY_PATH, if needed
if [ -f $SBOX_SESSION_DIR/ld_library_path_extras ]; then
@@ -1248,14 +1243,25 @@ unset SBOX_TOOLS_ROOT
# ------------
+#
+# We need to start "trampoline" host shell that is run under
+# influence of libsb2.so.1. When it exec's real shell, we can
+# be sure that all mappings and exec rules are in place.
+#
if [ $# -gt 0 -o "$STDIN" = true ]; then
binary="$1"
shift 1
args="$@"
- exec $SBOX_FAKEROOT_PREFIX sb2-monitor -L $SBOX_LIBSB2 -x $SBOX_DIR/share/scratchbox2/scripts/sb2-exitreport \
- -- $SHELL -c "$binary $args"
+ exec $SBOX_FAKEROOT_PREFIX sb2-monitor \
+ -L $SBOX_LIBSB2 \
+ -x $SBOX_DIR/share/scratchbox2/scripts/sb2-exitreport \
+ -- \
+ $SHELL -c "exec $SHELL -c '$binary $args'"
else
- exec $SBOX_FAKEROOT_PREFIX sb2-monitor -L $SBOX_LIBSB2 -x $SBOX_DIR/share/scratchbox2/scripts/sb2-exitreport \
- -- $SHELL --noprofile --norc
+ exec $SBOX_FAKEROOT_PREFIX sb2-monitor \
+ -L $SBOX_LIBSB2 \
+ -x $SBOX_DIR/share/scratchbox2/scripts/sb2-exitreport \
+ -- \
+ $SHELL -c \
+ "export PS1='$PS1'; exec $SHELL --noprofile --norc"
fi
-