summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-08-02 16:40:14 +0300
committerAvi Kivity <avi@redhat.com>2010-08-02 16:40:14 +0300
commitb83d4fb84583ce2c7860584750d42183f7fef5c5 (patch)
treeafc686386b73a8f7a911047ac231ce89d79f2502
parent01ac6428a04576ae6f84f07d82c98da304b9ac77 (diff)
parentad7ee4ad6c3a5388acf94dd532d291ea6d3a5972 (diff)
Merge remote branch 'upstream' into next
* upstream: (43 commits) Initialize a variable in all cases Fix uint8_t comparison with negative value Fix a warning on OpenSolaris Correctly identify multiple cpus in SMP systems Remove unused constant jazz led: Fix debug prints xilinx-s3adsp: Add support for loading u-boot images. xilinx-s3adsp: Fix loading of raw binaries. Remove unused eventfd.h migration: Accept 'cont' only after successful incoming migration mips64el: fulong: PCI_DEVFN() clean up. remove pointless if from vl.c fix variable type in qemu-io.c remove dead code from hw/loader.c savevm: Fix memory leak of compat struct virtio-serial: Check if more max_ports specified than we can handle linux-user: fix build on hosts not using guest base linux-user: Protect against allocation failure in load_symbols. cris: Correct settls1 testcase. cris: Correct ADDO and ADDOQ testcases. ... Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--VERSION2
-rw-r--r--block-migration.c6
-rw-r--r--block.c32
-rw-r--r--block.h1
-rw-r--r--block_int.h4
-rw-r--r--blockdev.c1
-rw-r--r--cpu-all.h2
-rw-r--r--elf.h44
-rw-r--r--hw/ide/core.c18
-rw-r--r--hw/jazz_led.c21
-rw-r--r--hw/loader.c5
-rw-r--r--hw/mips_fulong2e.c14
-rw-r--r--hw/petalogix_s3adsp1800_mmu.c13
-rw-r--r--hw/vhost.c1
-rw-r--r--hw/vhost_net.c1
-rw-r--r--hw/virtio-blk.c8
-rw-r--r--hw/virtio-pci.c1
-rw-r--r--hw/virtio-serial-bus.c10
-rw-r--r--hw/virtio.h1
-rw-r--r--linux-user/elfload.c1799
-rw-r--r--linux-user/linuxload.c17
-rw-r--r--linux-user/mmap.c14
-rw-r--r--linux-user/qemu.h7
-rw-r--r--migration.c2
-rw-r--r--monitor.c4
-rw-r--r--net/tap-solaris.c1
-rw-r--r--qemu-io.c4
-rw-r--r--qemu-options.hx2
-rw-r--r--qerror.c4
-rw-r--r--qerror.h3
-rw-r--r--savevm.c6
-rw-r--r--sysemu.h1
-rw-r--r--target-mips/op_helper.c3
-rw-r--r--target-mips/translate.c3
-rw-r--r--target-mips/translate_init.c4
-rw-r--r--tests/cris/check_addo.c4
-rw-r--r--tests/cris/check_addoq.c2
-rw-r--r--tests/cris/check_settls1.c10
-rw-r--r--ui/vnc-enc-tight.c30
-rw-r--r--vl.c6
40 files changed, 972 insertions, 1139 deletions
diff --git a/VERSION b/VERSION
index bc4cbfa42..d82f77b7c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.12.90
+0.13.50
diff --git a/block-migration.c b/block-migration.c
index a77106e25..8eda307d7 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -586,6 +586,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
addr >>= BDRV_SECTOR_BITS;
if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
+ int ret;
/* get device name */
len = qemu_get_byte(f);
qemu_get_buffer(f, (uint8_t *)device_name, len);
@@ -601,9 +602,12 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
buf = qemu_malloc(BLOCK_SIZE);
qemu_get_buffer(f, buf, BLOCK_SIZE);
- bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
+ ret = bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
qemu_free(buf);
+ if (ret < 0) {
+ return ret;
+ }
} else if (flags & BLK_MIG_FLAG_PROGRESS) {
if (!banner_printed) {
printf("Receiving block device images\n");
diff --git a/block.c b/block.c
index f837876d8..452ae94ee 100644
--- a/block.c
+++ b/block.c
@@ -330,7 +330,7 @@ BlockDriver *bdrv_find_protocol(const char *filename)
return NULL;
}
-static BlockDriver *find_image_format(const char *filename)
+static int find_image_format(const char *filename, BlockDriver **pdrv)
{
int ret, score, score_max;
BlockDriver *drv1, *drv;
@@ -338,19 +338,27 @@ static BlockDriver *find_image_format(const char *filename)
BlockDriverState *bs;
ret = bdrv_file_open(&bs, filename, 0);
- if (ret < 0)
- return NULL;
+ if (ret < 0) {
+ *pdrv = NULL;
+ return ret;
+ }
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
if (bs->sg || !bdrv_is_inserted(bs)) {
bdrv_delete(bs);
- return bdrv_find_format("raw");
+ drv = bdrv_find_format("raw");
+ if (!drv) {
+ ret = -ENOENT;
+ }
+ *pdrv = drv;
+ return ret;
}
ret = bdrv_pread(bs, 0, buf, sizeof(buf));
bdrv_delete(bs);
if (ret < 0) {
- return NULL;
+ *pdrv = NULL;
+ return ret;
}
score_max = 0;
@@ -364,7 +372,11 @@ static BlockDriver *find_image_format(const char *filename)
}
}
}
- return drv;
+ if (!drv) {
+ ret = -ENOENT;
+ }
+ *pdrv = drv;
+ return ret;
}
/**
@@ -571,12 +583,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
/* Find the right image format driver */
if (!drv) {
- drv = find_image_format(filename);
+ ret = find_image_format(filename, &drv);
probed = 1;
}
if (!drv) {
- ret = -ENOENT;
goto unlink_and_fail;
}
@@ -1800,6 +1811,11 @@ int bdrv_can_snapshot(BlockDriverState *bs)
return 1;
}
+int bdrv_is_snapshot(BlockDriverState *bs)
+{
+ return !!(bs->open_flags & BDRV_O_SNAPSHOT);
+}
+
BlockDriverState *bdrv_snapshots(void)
{
BlockDriverState *bs;
diff --git a/block.h b/block.h
index c2a7e4c76..db131a343 100644
--- a/block.h
+++ b/block.h
@@ -202,6 +202,7 @@ const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size);
int bdrv_can_snapshot(BlockDriverState *bs);
+int bdrv_is_snapshot(BlockDriverState *bs);
BlockDriverState *bdrv_snapshots(void);
int bdrv_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info);
diff --git a/block_int.h b/block_int.h
index 96ff4cf1b..f075a8cba 100644
--- a/block_int.h
+++ b/block_int.h
@@ -243,7 +243,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
_conf.logical_block_size, 512), \
DEFINE_PROP_UINT16("physical_block_size", _state, \
_conf.physical_block_size, 512), \
- DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 512), \
- DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 512)
+ DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
+ DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0)
#endif /* BLOCK_INT_H */
diff --git a/blockdev.c b/blockdev.c
index 5aa441a80..78c286cf6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -603,6 +603,7 @@ int do_change_block(Monitor *mon, const char *device,
return -1;
}
bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
+ bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1;
diff --git a/cpu-all.h b/cpu-all.h
index 224ca40c1..67a32664d 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -629,8 +629,10 @@ extern unsigned long guest_base;
extern int have_guest_base;
extern unsigned long reserved_va;
#define GUEST_BASE guest_base
+#define RESERVED_VA reserved_va
#else
#define GUEST_BASE 0ul
+#define RESERVED_VA 0ul
#endif
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
diff --git a/elf.h b/elf.h
index eb9e3bece..7067c90fb 100644
--- a/elf.h
+++ b/elf.h
@@ -147,8 +147,37 @@ typedef int64_t Elf64_Sxword;
#define DT_DEBUG 21
#define DT_TEXTREL 22
#define DT_JMPREL 23
+#define DT_BINDNOW 24
+#define DT_INIT_ARRAY 25
+#define DT_FINI_ARRAY 26
+#define DT_INIT_ARRAYSZ 27
+#define DT_FINI_ARRAYSZ 28
+#define DT_RUNPATH 29
+#define DT_FLAGS 30
+#define DT_LOOS 0x6000000d
+#define DT_HIOS 0x6ffff000
#define DT_LOPROC 0x70000000
#define DT_HIPROC 0x7fffffff
+
+/* DT_ entries which fall between DT_VALRNGLO and DT_VALRNDHI use
+ the d_val field of the Elf*_Dyn structure. I.e. they contain scalars. */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_VALRNGHI 0x6ffffdff
+
+/* DT_ entries which fall between DT_ADDRRNGLO and DT_ADDRRNGHI use
+ the d_ptr field of the Elf*_Dyn structure. I.e. they contain pointers. */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_ADDRRNGHI 0x6ffffeff
+
+#define DT_VERSYM 0x6ffffff0
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+#define DT_FLAGS_1 0x6ffffffb
+#define DT_VERDEF 0x6ffffffc
+#define DT_VERDEFNUM 0x6ffffffd
+#define DT_VERNEED 0x6ffffffe
+#define DT_VERNEEDNUM 0x6fffffff
+
#define DT_MIPS_RLD_VERSION 0x70000001
#define DT_MIPS_TIME_STAMP 0x70000002
#define DT_MIPS_ICHECKSUM 0x70000003
@@ -207,6 +236,21 @@ typedef int64_t Elf64_Sxword;
#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
#define AT_CLKTCK 17 /* frequency at which times() increments */
+#define AT_FPUCW 18 /* info about fpu initialization by kernel */
+#define AT_DCACHEBSIZE 19 /* data cache block size */
+#define AT_ICACHEBSIZE 20 /* instruction cache block size */
+#define AT_UCACHEBSIZE 21 /* unified cache block size */
+#define AT_IGNOREPPC 22 /* ppc only; entry should be ignored */
+#define AT_SECURE 23 /* boolean, was exec suid-like? */
+#define AT_BASE_PLATFORM 24 /* string identifying real platforms */
+#define AT_RANDOM 25 /* address of 16 random bytes */
+#define AT_EXECFN 31 /* filename of the executable */
+#define AT_SYSINFO 32 /* address of kernel entry point */
+#define AT_SYSINFO_EHDR 33 /* address of kernel vdso */
+#define AT_L1I_CACHESHAPE 34 /* shapes of the caches: */
+#define AT_L1D_CACHESHAPE 35 /* bits 0-3: cache associativity. */
+#define AT_L2_CACHESHAPE 36 /* bits 4-7: log2 of line size. */
+#define AT_L3_CACHESHAPE 37 /* val&~255: cache size. */
typedef struct dynamic{
Elf32_Sword d_tag;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index db000831e..631673fc0 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1643,6 +1643,21 @@ static void ide_atapi_cmd(IDEState *s)
ide_atapi_cmd_reply(s, len, max_len);
break;
}
+ case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
+ max_len = ube16_to_cpu(packet + 7);
+
+ if (packet[1] & 0x01) { /* polling */
+ /* We don't support any event class (yet). */
+ cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
+ buf[2] = 0x80; /* No Event Available (NEA) */
+ buf[3] = 0x00; /* Empty supported event classes */
+ ide_atapi_cmd_reply(s, 4, max_len);
+ } else { /* asynchronous mode */
+ /* Only polling is supported, asynchronous mode is not. */
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ }
+ break;
default:
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_ILLEGAL_OPCODE);
@@ -2764,8 +2779,7 @@ static int ide_drive_pio_post_load(void *opaque, int version_id)
{
IDEState *s = opaque;
- if (s->end_transfer_fn_idx < 0 ||
- s->end_transfer_fn_idx > ARRAY_SIZE(transfer_end_table)) {
+ if (s->end_transfer_fn_idx > ARRAY_SIZE(transfer_end_table)) {
return -EINVAL;
}
s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index 18780e937..4cb680c3e 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -29,6 +29,15 @@
//#define DEBUG_LED
+#ifdef DEBUG_LED
+#define DPRINTF(fmt, ...) \
+do { printf("jazz led: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "jazz led ERROR: " fmt , ## __VA_ARGS__);} while (0)
+
typedef enum {
REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
} screen_state_t;
@@ -49,12 +58,12 @@ static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
val = s->segments;
break;
default:
-#ifdef DEBUG_LED
- printf("jazz led: invalid read [0x%x]\n", relative_addr);
-#endif
+ BADF("invalid read at [" TARGET_FMT_plx "]\n", addr);
val = 0;
}
+ DPRINTF("read addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);
+
return val;
}
@@ -92,15 +101,15 @@ static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LedState *s = opaque;
+ DPRINTF("write addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);
+
switch (addr) {
case 0:
s->segments = val;
s->state |= REDRAW_SEGMENTS;
break;
default:
-#ifdef DEBUG_LED
- printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
-#endif
+ BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr);
break;
}
}
diff --git a/hw/loader.c b/hw/loader.c
index 79a6f9518..49ac1fa1c 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -733,11 +733,6 @@ int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size)
s = rom->data;
l = rom->romsize;
- if (rom->addr < addr) {
- d = dest;
- s += (addr - rom->addr);
- l -= (addr - rom->addr);
- }
if ((d + l) > (dest + size)) {
l = dest - d;
}
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index a9bbff64b..c6c13ca99 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -219,8 +219,8 @@ uint8_t eeprom_spd[0x80] = {
#ifdef HAS_AUDIO
static void audio_init (PCIBus *pci_bus)
{
- vt82c686b_ac97_init(pci_bus, (FULONG2E_VIA_SLOT << 3) + 5);
- vt82c686b_mc97_init(pci_bus, (FULONG2E_VIA_SLOT << 3) + 6);
+ vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
+ vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
}
#endif
@@ -349,18 +349,18 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
}
- via_devfn = vt82c686b_init(pci_bus, FULONG2E_VIA_SLOT << 3);
+ via_devfn = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
if (via_devfn < 0) {
fprintf(stderr, "vt82c686b_init error \n");
exit(1);
}
isa_bus_irqs(i8259);
- vt82c686b_ide_init(pci_bus, hd, (FULONG2E_VIA_SLOT << 3) + 1);
- usb_uhci_vt82c686b_init(pci_bus, (FULONG2E_VIA_SLOT << 3) + 2);
- usb_uhci_vt82c686b_init(pci_bus, (FULONG2E_VIA_SLOT << 3) + 3);
+ vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
+ usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2));
+ usb_uhci_vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3));
- smbus = vt82c686b_pm_init(pci_bus, (FULONG2E_VIA_SLOT << 3) + 4,
+ smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
0xeee1, NULL);
eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
memcpy(eeprom_buf, eeprom_spd, sizeof(eeprom_spd));
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 70b6a36e1..fcbb825d7 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -179,11 +179,22 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
}
/* Always boot into physical ram. */
boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
+
+ /* If it wasn't an ELF image, try an u-boot image. */
+ if (kernel_size < 0) {
+ target_phys_addr_t uentry, loadaddr;
+
+ kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
+ boot_info.bootstrap_pc = uentry;
+ high = (loadaddr + kernel_size + 3) & ~3;
+ }
+
+ /* Not an ELF image nor an u-boot image, try a RAW image. */
if (kernel_size < 0) {
- /* If we failed loading ELF's try a raw image. */
kernel_size = load_image_targphys(kernel_filename, ddr_base,
ram_size);
boot_info.bootstrap_pc = ddr_base;
+ high = (ddr_base + kernel_size + 3) & ~3;
}
boot_info.cmdline = high + 4096;
diff --git a/hw/vhost.c b/hw/vhost.c
index 65709d005..34c4745d8 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -11,7 +11,6 @@
*/
#include <sys/ioctl.h>
-#include <sys/eventfd.h>
#include "vhost.h"
#include "hw/hw.h"
/* For range_get_last */
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index 606aa0c1c..0c00de272 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -20,7 +20,6 @@
#ifdef CONFIG_VHOST_NET
#include <linux/vhost.h>
-#include <sys/eventfd.h>
#include <sys/socket.h>
#include <linux/kvm.h>
#include <fcntl.h>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index f50069d20..490cd4105 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -28,6 +28,7 @@ typedef struct VirtIOBlock
BlockConf *conf;
unsigned short sector_mask;
char sn[BLOCK_SERIAL_STRLEN];
+ DeviceState *qdev;
} VirtIOBlock;
static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -522,9 +523,16 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
+ s->qdev = dev;
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s);
bdrv_set_removable(s->bs, 0);
return &s->vdev;
}
+
+void virtio_blk_exit(VirtIODevice *vdev)
+{
+ VirtIOBlock *s = to_virtio_blk(vdev);
+ unregister_savevm(s->qdev, "virtio-blk", s);
+}
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 66a8948c9..3a0702455 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -603,6 +603,7 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ virtio_blk_exit(proxy->vdev);
blockdev_mark_auto_del(proxy->block.bs);
return virtio_exit_pci(pci_dev);
}
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 8e611c03e..0586b8985 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -734,11 +734,19 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
{
VirtIOSerial *vser;
VirtIODevice *vdev;
- uint32_t i;
+ uint32_t i, max_supported_ports;
if (!max_nr_ports)
return NULL;
+ /* Each port takes 2 queues, and one pair is for the control queue */
+ max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
+
+ if (max_nr_ports > max_supported_ports) {
+ error_report("maximum ports supported: %u", max_supported_ports);
+ return NULL;
+ }
+
vdev = virtio_common_init("virtio-serial", VIRTIO_ID_CONSOLE,
sizeof(struct virtio_console_config),
sizeof(VirtIOSerial));
diff --git a/hw/virtio.h b/hw/virtio.h
index e4306cd75..30e472aba 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -194,6 +194,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
void virtio_net_exit(VirtIODevice *vdev);
+void virtio_blk_exit(VirtIODevice *vdev);
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index accb44d9d..33d776de4 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -35,18 +35,17 @@
* These occupy the top three bytes.
*/
enum {
- ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
- FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
- * (signal handling)
- */
- MMAP_PAGE_ZERO = 0x0100000,
- ADDR_COMPAT_LAYOUT = 0x0200000,
- READ_IMPLIES_EXEC = 0x0400000,
- ADDR_LIMIT_32BIT = 0x0800000,
- SHORT_INODE = 0x1000000,
- WHOLE_SECONDS = 0x2000000,
- STICKY_TIMEOUTS = 0x4000000,
- ADDR_LIMIT_3GB = 0x8000000,
+ ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
+ FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to
+ descriptors (signal handling) */
+ MMAP_PAGE_ZERO = 0x0100000,
+ ADDR_COMPAT_LAYOUT = 0x0200000,
+ READ_IMPLIES_EXEC = 0x0400000,
+ ADDR_LIMIT_32BIT = 0x0800000,
+ SHORT_INODE = 0x1000000,
+ WHOLE_SECONDS = 0x2000000,
+ STICKY_TIMEOUTS = 0x4000000,
+ ADDR_LIMIT_3GB = 0x8000000,
};
/*
@@ -56,36 +55,35 @@ enum {
* conflict with error returns.
*/
enum {
- PER_LINUX = 0x0000,
- PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
- PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
- PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
- PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
- PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
- WHOLE_SECONDS | SHORT_INODE,
- PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
- PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
- PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
- PER_BSD = 0x0006,
- PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
- PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
- PER_LINUX32 = 0x0008,
- PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
- PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
- PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
- PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
- PER_RISCOS = 0x000c,
- PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
- PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
- PER_OSF4 = 0x000f, /* OSF/1 v4 */
- PER_HPUX = 0x0010,
- PER_MASK = 0x00ff,
+ PER_LINUX = 0x0000,
+ PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
+ PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
+ PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+ PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+ PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
+ PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+ PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+ PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
+ PER_BSD = 0x0006,
+ PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
+ PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+ PER_LINUX32 = 0x0008,
+ PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
+ PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+ PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+ PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+ PER_RISCOS = 0x000c,
+ PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
+ PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+ PER_OSF4 = 0x000f, /* OSF/1 v4 */
+ PER_HPUX = 0x0010,
+ PER_MASK = 0x00ff,
};
/*
* Return the base personality without flags.
*/
-#define personality(pers) (pers & PER_MASK)
+#define personality(pers) (pers & PER_MASK)
/* this flag is uneffective under linux too, should be deleted */
#ifndef MAP_DENYWRITE
@@ -97,15 +95,21 @@ enum {
#define ELIBBAD 80
#endif
-typedef target_ulong target_elf_greg_t;
+#ifdef TARGET_WORDS_BIGENDIAN
+#define ELF_DATA ELFDATA2MSB
+#else
+#define ELF_DATA ELFDATA2LSB
+#endif
+
+typedef target_ulong target_elf_greg_t;
#ifdef USE_UID16
-typedef uint16_t target_uid_t;
-typedef uint16_t target_gid_t;
+typedef uint16_t target_uid_t;
+typedef uint16_t target_gid_t;
#else
-typedef uint32_t target_uid_t;
-typedef uint32_t target_gid_t;
+typedef uint32_t target_uid_t;
+typedef uint32_t target_gid_t;
#endif
-typedef int32_t target_pid_t;
+typedef int32_t target_pid_t;
#ifdef TARGET_I386
@@ -126,7 +130,7 @@ static const char *get_elf_platform(void)
static uint32_t get_elf_hwcap(void)
{
- return thread_env->cpuid_features;
+ return thread_env->cpuid_features;
}
#ifdef TARGET_X86_64
@@ -134,7 +138,6 @@ static uint32_t get_elf_hwcap(void)
#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
#define ELF_CLASS ELFCLASS64
-#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_X86_64
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
@@ -197,11 +200,11 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
/*
* These are used to set parameters in the core dumps.
*/
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2LSB
-#define ELF_ARCH EM_386
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_386
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
regs->esp = infop->start_stack;
regs->eip = infop->entry;
@@ -249,7 +252,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#endif
#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
+#define ELF_EXEC_PAGESIZE 4096
#endif
@@ -259,21 +262,17 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#define elf_check_arch(x) ( (x) == EM_ARM )
-#define ELF_CLASS ELFCLASS32
-#ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA ELFDATA2MSB
-#else
-#define ELF_DATA ELFDATA2LSB
-#endif
-#define ELF_ARCH EM_ARM
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_ARM
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
abi_long stack = infop->start_stack;
memset(regs, 0, sizeof(*regs));
regs->ARM_cpsr = 0x10;
if (infop->entry & 1)
- regs->ARM_cpsr |= CPSR_T;
+ regs->ARM_cpsr |= CPSR_T;
regs->ARM_pc = infop->entry & 0xfffffffe;
regs->ARM_sp = infop->start_stack;
/* FIXME - what to for failure of get_user()? */
@@ -313,30 +312,30 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
}
#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
+#define ELF_EXEC_PAGESIZE 4096
enum
{
- ARM_HWCAP_ARM_SWP = 1 << 0,
- ARM_HWCAP_ARM_HALF = 1 << 1,
- ARM_HWCAP_ARM_THUMB = 1 << 2,
- ARM_HWCAP_ARM_26BIT = 1 << 3,
- ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
- ARM_HWCAP_ARM_FPA = 1 << 5,
- ARM_HWCAP_ARM_VFP = 1 << 6,
- ARM_HWCAP_ARM_EDSP = 1 << 7,
- ARM_HWCAP_ARM_JAVA = 1 << 8,
- ARM_HWCAP_ARM_IWMMXT = 1 << 9,
- ARM_HWCAP_ARM_THUMBEE = 1 << 10,
- ARM_HWCAP_ARM_NEON = 1 << 11,
- ARM_HWCAP_ARM_VFPv3 = 1 << 12,
- ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
+ ARM_HWCAP_ARM_SWP = 1 << 0,
+ ARM_HWCAP_ARM_HALF = 1 << 1,
+ ARM_HWCAP_ARM_THUMB = 1 << 2,
+ ARM_HWCAP_ARM_26BIT = 1 << 3,
+ ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
+ ARM_HWCAP_ARM_FPA = 1 << 5,
+ ARM_HWCAP_ARM_VFP = 1 << 6,
+ ARM_HWCAP_ARM_EDSP = 1 << 7,
+ ARM_HWCAP_ARM_JAVA = 1 << 8,
+ ARM_HWCAP_ARM_IWMMXT = 1 << 9,
+ ARM_HWCAP_ARM_THUMBEE = 1 << 10,
+ ARM_HWCAP_ARM_NEON = 1 << 11,
+ ARM_HWCAP_ARM_VFPv3 = 1 << 12,
+ ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
};
-#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
- | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
- | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
- | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
+#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
+ | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
+ | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
+ | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
#endif
@@ -352,12 +351,12 @@ enum
#endif
#define ELF_CLASS ELFCLASS64
-#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_SPARCV9
-#define STACK_BIAS 2047
+#define STACK_BIAS 2047
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
#ifndef TARGET_ABI32
regs->tstate = 0;
@@ -381,10 +380,10 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define elf_check_arch(x) ( (x) == EM_SPARC )
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_SPARC
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
regs->psr = 0;
regs->pc = infop->entry;
@@ -404,22 +403,17 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define elf_check_arch(x) ( (x) == EM_PPC64 )
-#define ELF_CLASS ELFCLASS64
+#define ELF_CLASS ELFCLASS64
#else
#define elf_check_arch(x) ( (x) == EM_PPC )
-#define ELF_CLASS ELFCLASS32
+#define ELF_CLASS ELFCLASS32
#endif
-#ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA ELFDATA2MSB
-#else
-#define ELF_DATA ELFDATA2LSB
-#endif
-#define ELF_ARCH EM_PPC
+#define ELF_ARCH EM_PPC
/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
See arch/powerpc/include/asm/cputable.h. */
@@ -464,7 +458,7 @@ static uint32_t get_elf_hwcap(void)
/* We don't have to be terribly complete here; the high points are
Altivec/FP/SPE support. Anything else is just a bonus. */
-#define GET_FEATURE(flag, feature) \
+#define GET_FEATURE(flag, feature) \
do {if (e->insns_flags & flag) features |= feature; } while(0)
GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
@@ -480,15 +474,6 @@ static uint32_t get_elf_hwcap(void)
}
/*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE 19
-#define AT_ICACHEBSIZE 20
-#define AT_UCACHEBSIZE 21
-/* A special ignored type value for PPC, for glibc compatibility. */
-#define AT_IGNOREPPC 22
-/*
* The requirements here are:
* - keep the final alignment of sp (sp & 0xf)
* - make sure the 32-bit value at the first 16 byte aligned position of
@@ -498,17 +483,17 @@ static uint32_t get_elf_hwcap(void)
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
#define DLINFO_ARCH_ITEMS 5
-#define ARCH_DLINFO \
-do { \
- NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
- NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
- NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
- /* \
- * Now handle glibc compatibility. \
- */ \
- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
- } while (0)
+#define ARCH_DLINFO \
+ do { \
+ NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
+ NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
+ NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
+ /* \
+ * Now handle glibc compatibility. \
+ */ \
+ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+ } while (0)
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
{
@@ -546,7 +531,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
}
#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
+#define ELF_EXEC_PAGESIZE 4096
#endif
@@ -561,14 +546,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#else
#define ELF_CLASS ELFCLASS32
#endif
-#ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA ELFDATA2MSB
-#else
-#define ELF_DATA ELFDATA2LSB
-#endif
#define ELF_ARCH EM_MIPS
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
regs->cp0_status = 2 << CP0St_KSU;
regs->cp0_epc = infop->entry;
@@ -632,10 +613,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_MICROBLAZE
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
regs->pc = infop->entry;
regs->r1 = infop->start_stack;
@@ -671,14 +652,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#define elf_check_arch(x) ( (x) == EM_SH )
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_SH
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
- /* Check other registers XXXXX */
- regs->pc = infop->entry;
- regs->regs[15] = infop->start_stack;
+ /* Check other registers XXXXX */
+ regs->pc = infop->entry;
+ regs->regs[15] = infop->start_stack;
}
/* See linux kernel: arch/sh/include/asm/elf.h. */
@@ -696,7 +677,8 @@ enum {
TARGET_REG_SYSCALL = 22
};
-static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
+ const CPUState *env)
{
int i;
@@ -725,12 +707,12 @@ static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState
#define elf_check_arch(x) ( (x) == EM_CRIS )
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_CRIS
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
- regs->erp = infop->entry;
+ regs->erp = infop->entry;
}
#define ELF_EXEC_PAGESIZE 8192
@@ -743,14 +725,14 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define elf_check_arch(x) ( (x) == EM_68K )
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
-#define ELF_ARCH EM_68K
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_68K
/* ??? Does this need to do anything?
-#define ELF_PLAT_INIT(_r) */
+ #define ELF_PLAT_INIT(_r) */
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
regs->usp = infop->start_stack;
regs->sr = 0;
@@ -786,7 +768,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
}
#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 8192
+#define ELF_EXEC_PAGESIZE 8192
#endif
@@ -797,10 +779,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#define elf_check_arch(x) ( (x) == ELF_ARCH )
#define ELF_CLASS ELFCLASS64
-#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_ALPHA
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
{
regs->pc = infop->entry;
regs->ps = 8;
@@ -830,14 +812,14 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
struct exec
{
- unsigned int a_info; /* Use macros N_MAGIC, etc for access */
- unsigned int a_text; /* length of text, in bytes */
- unsigned int a_data; /* length of data, in bytes */
- unsigned int a_bss; /* length of uninitialized data area, in bytes */
- unsigned int a_syms; /* length of symbol table data in file, in bytes */
- unsigned int a_entry; /* start address */
- unsigned int a_trsize; /* length of relocation info for text, in bytes */
- unsigned int a_drsize; /* length of relocation info for data, in bytes */
+ unsigned int a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned int a_text; /* length of text, in bytes */
+ unsigned int a_data; /* length of data, in bytes */
+ unsigned int a_bss; /* length of uninitialized data area, in bytes */
+ unsigned int a_syms; /* length of symbol table data in file, in bytes */
+ unsigned int a_entry; /* start address */
+ unsigned int a_trsize; /* length of relocation info for text, in bytes */
+ unsigned int a_drsize; /* length of relocation info for data, in bytes */
};
@@ -847,72 +829,66 @@ struct exec
#define ZMAGIC 0413
#define QMAGIC 0314
-/* max code+data+bss space allocated to elf interpreter */
-#define INTERP_MAP_SIZE (32 * 1024 * 1024)
-
-/* max code+data+bss+brk space allocated to ET_DYN executables */
-#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
-
/* Necessary parameters */
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
-#define INTERPRETER_NONE 0
-#define INTERPRETER_AOUT 1
-#define INTERPRETER_ELF 2
-
#define DLINFO_ITEMS 12
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
{
- memcpy(to, from, n);
+ memcpy(to, from, n);
}
-static int load_aout_interp(void * exptr, int interp_fd);
-
#ifdef BSWAP_NEEDED
static void bswap_ehdr(struct elfhdr *ehdr)
{
- bswap16s(&ehdr->e_type); /* Object file type */
- bswap16s(&ehdr->e_machine); /* Architecture */
- bswap32s(&ehdr->e_version); /* Object file version */
- bswaptls(&ehdr->e_entry); /* Entry point virtual address */
- bswaptls(&ehdr->e_phoff); /* Program header table file offset */
- bswaptls(&ehdr->e_shoff); /* Section header table file offset */
- bswap32s(&ehdr->e_flags); /* Processor-specific flags */
- bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
- bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
- bswap16s(&ehdr->e_phnum); /* Program header table entry count */
- bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
- bswap16s(&ehdr->e_shnum); /* Section header table entry count */
- bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
-}
-
-static void bswap_phdr(struct elf_phdr *phdr)
-{
- bswap32s(&phdr->p_type); /* Segment type */
- bswaptls(&phdr->p_offset); /* Segment file offset */
- bswaptls(&phdr->p_vaddr); /* Segment virtual address */
- bswaptls(&phdr->p_paddr); /* Segment physical address */
- bswaptls(&phdr->p_filesz); /* Segment size in file */
- bswaptls(&phdr->p_memsz); /* Segment size in memory */
- bswap32s(&phdr->p_flags); /* Segment flags */
- bswaptls(&phdr->p_align); /* Segment alignment */
-}
-
-static void bswap_shdr(struct elf_shdr *shdr)
-{
- bswap32s(&shdr->sh_name);
- bswap32s(&shdr->sh_type);
- bswaptls(&shdr->sh_flags);
- bswaptls(&shdr->sh_addr);
- bswaptls(&shdr->sh_offset);
- bswaptls(&shdr->sh_size);
- bswap32s(&shdr->sh_link);
- bswap32s(&shdr->sh_info);
- bswaptls(&shdr->sh_addralign);
- bswaptls(&shdr->sh_entsize);
+ bswap16s(&ehdr->e_type); /* Object file type */
+ bswap16s(&ehdr->e_machine); /* Architecture */
+ bswap32s(&ehdr->e_version); /* Object file version */
+ bswaptls(&ehdr->e_entry); /* Entry point virtual address */
+ bswaptls(&ehdr->e_phoff); /* Program header table file offset */
+ bswaptls(&ehdr->e_shoff); /* Section header table file offset */
+ bswap32s(&ehdr->e_flags); /* Processor-specific flags */
+ bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
+ bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
+ bswap16s(&ehdr->e_phnum); /* Program header table entry count */
+ bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
+ bswap16s(&ehdr->e_shnum); /* Section header table entry count */
+ bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
+}
+
+static void bswap_phdr(struct elf_phdr *phdr, int phnum)
+{
+ int i;
+ for (i = 0; i < phnum; ++i, ++phdr) {
+ bswap32s(&phdr->p_type); /* Segment type */
+ bswap32s(&phdr->p_flags); /* Segment flags */
+ bswaptls(&phdr->p_offset); /* Segment file offset */
+ bswaptls(&phdr->p_vaddr); /* Segment virtual address */
+ bswaptls(&phdr->p_paddr); /* Segment physical address */
+ bswaptls(&phdr->p_filesz); /* Segment size in file */
+ bswaptls(&phdr->p_memsz); /* Segment size in memory */
+ bswaptls(&phdr->p_align); /* Segment alignment */
+ }
+}
+
+static void bswap_shdr(struct elf_shdr *shdr, int shnum)
+{
+ int i;
+ for (i = 0; i < shnum; ++i, ++shdr) {
+ bswap32s(&shdr->sh_name);
+ bswap32s(&shdr->sh_type);
+ bswaptls(&shdr->sh_flags);
+ bswaptls(&shdr->sh_addr);
+ bswaptls(&shdr->sh_offset);
+ bswaptls(&shdr->sh_size);
+ bswap32s(&shdr->sh_link);
+ bswap32s(&shdr->sh_info);
+ bswaptls(&shdr->sh_addralign);
+ bswaptls(&shdr->sh_entsize);
+ }
}
static void bswap_sym(struct elf_sym *sym)
@@ -922,21 +898,41 @@ static void bswap_sym(struct elf_sym *sym)
bswaptls(&sym->st_size);
bswap16s(&sym->st_shndx);
}
+#else
+static inline void bswap_ehdr(struct elfhdr *ehdr) { }
+static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
+static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
+static inline void bswap_sym(struct elf_sym *sym) { }
#endif
#ifdef USE_ELF_CORE_DUMP
static int elf_core_dump(int, const CPUState *);
+#endif /* USE_ELF_CORE_DUMP */
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
-#ifdef BSWAP_NEEDED
-static void bswap_note(struct elf_note *en)
+/* Verify the portions of EHDR within E_IDENT for the target.
+ This can be performed before bswapping the entire header. */
+static bool elf_check_ident(struct elfhdr *ehdr)
{
- bswap32s(&en->n_namesz);
- bswap32s(&en->n_descsz);
- bswap32s(&en->n_type);
+ return (ehdr->e_ident[EI_MAG0] == ELFMAG0
+ && ehdr->e_ident[EI_MAG1] == ELFMAG1
+ && ehdr->e_ident[EI_MAG2] == ELFMAG2
+ && ehdr->e_ident[EI_MAG3] == ELFMAG3
+ && ehdr->e_ident[EI_CLASS] == ELF_CLASS
+ && ehdr->e_ident[EI_DATA] == ELF_DATA
+ && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
}
-#endif /* BSWAP_NEEDED */
-#endif /* USE_ELF_CORE_DUMP */
+/* Verify the portions of EHDR outside of E_IDENT for the target.
+ This has to wait until after bswapping the header. */
+static bool elf_check_ehdr(struct elfhdr *ehdr)
+{
+ return (elf_check_arch(ehdr->e_machine)
+ && ehdr->e_ehsize == sizeof(struct elfhdr)
+ && ehdr->e_phentsize == sizeof(struct elf_phdr)
+ && ehdr->e_shentsize == sizeof(struct elf_shdr)
+ && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
+}
/*
* 'copy_elf_strings()' copies argument/envelope strings from user
@@ -951,24 +947,24 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
int len, offset = 0;
if (!p) {
- return 0; /* bullet-proofing */
+ return 0; /* bullet-proofing */
}
while (argc-- > 0) {
tmp = argv[argc];
if (!tmp) {
- fprintf(stderr, "VFS: argc is wrong");
- exit(-1);
- }
+ fprintf(stderr, "VFS: argc is wrong");
+ exit(-1);
+ }
tmp1 = tmp;
- while (*tmp++);
- len = tmp - tmp1;
- if (p < len) { /* this shouldn't happen - 128kB */
- return 0;
- }
- while (len) {
- --p; --tmp; --len;
- if (--offset < 0) {
- offset = p % TARGET_PAGE_SIZE;
+ while (*tmp++);
+ len = tmp - tmp1;
+ if (p < len) { /* this shouldn't happen - 128kB */
+ return 0;
+ }
+ while (len) {
+ --p; --tmp; --len;
+ if (--offset < 0) {
+ offset = p % TARGET_PAGE_SIZE;
pag = (char *)page[p/TARGET_PAGE_SIZE];
if (!pag) {
pag = (char *)malloc(TARGET_PAGE_SIZE);
@@ -976,20 +972,20 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
page[p/TARGET_PAGE_SIZE] = pag;
if (!pag)
return 0;
- }
- }
- if (len == 0 || offset == 0) {
- *(pag + offset) = *tmp;
- }
- else {
- int bytes_to_copy = (len > offset) ? offset : len;
- tmp -= bytes_to_copy;
- p -= bytes_to_copy;
- offset -= bytes_to_copy;
- len -= bytes_to_copy;
- memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
- }
- }
+ }
+ }
+ if (len == 0 || offset == 0) {
+ *(pag + offset) = *tmp;
+ }
+ else {
+ int bytes_to_copy = (len > offset) ? offset : len;
+ tmp -= bytes_to_copy;
+ p -= bytes_to_copy;
+ offset -= bytes_to_copy;
+ len -= bytes_to_copy;
+ memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
+ }
+ }
}
return p;
}
@@ -997,332 +993,440 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
struct image_info *info)
{
- abi_ulong stack_base, size, error;
+ abi_ulong stack_base, size, error, guard;
int i;
/* Create enough stack to hold everything. If we don't use
- * it for args, we'll use it for something else...
- */
+ it for args, we'll use it for something else. */
size = guest_stack_size;
- if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+ if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
- error = target_mmap(0,
- size + qemu_host_page_size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
+ }
+ guard = TARGET_PAGE_SIZE;
+ if (guard < qemu_real_host_page_size) {
+ guard = qemu_real_host_page_size;
+ }
+
+ error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (error == -1) {
- perror("stk mmap");
+ perror("mmap stack");
exit(-1);
}
- /* we reserve one extra page at the top of the stack as guard */
- target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
- info->stack_limit = error;
- stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+ /* We reserve one extra page at the top of the stack as guard. */
+ target_mprotect(error, guard, PROT_NONE);
+
+ info->stack_limit = error + guard;
+ stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
p += stack_base;
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
- if (bprm->page[i]) {
- info->rss++;
+ if (bprm->page[i]) {
+ info->rss++;
/* FIXME - check return value of memcpy_to_target() for failure */
- memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
- free(bprm->page[i]);
- }
+ memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
+ free(bprm->page[i]);
+ }
stack_base += TARGET_PAGE_SIZE;
}
return p;
}
-static void set_brk(abi_ulong start, abi_ulong end)
-{
- /* page-align the start and end addresses... */
- start = HOST_PAGE_ALIGN(start);
- end = HOST_PAGE_ALIGN(end);
- if (end <= start)
- return;
- if(target_mmap(start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
- perror("cannot mmap brk");
- exit(-1);
- }
-}
-
-
-/* We need to explicitly zero any fractional pages after the data
- section (i.e. bss). This would contain the junk from the file that
- should not be in memory. */
-static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
-{
- abi_ulong nbyte;
-
- if (elf_bss >= last_bss)
- return;
-
- /* XXX: this is really a hack : if the real host page size is
- smaller than the target page size, some pages after the end
- of the file may not be mapped. A better fix would be to
- patch target_mmap(), but it is more complicated as the file
- size must be known */
- if (qemu_real_host_page_size < qemu_host_page_size) {
- abi_ulong end_addr, end_addr1;
- end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
- ~(qemu_real_host_page_size - 1);
- end_addr = HOST_PAGE_ALIGN(elf_bss);
- if (end_addr1 < end_addr) {
- mmap((void *)g2h(end_addr1), end_addr - end_addr1,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- }
- }
+/* Map and zero the bss. We need to explicitly zero any fractional pages
+ after the data section (i.e. bss). */
+static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
+{
+ uintptr_t host_start, host_map_start, host_end;
- nbyte = elf_bss & (qemu_host_page_size-1);
- if (nbyte) {
- nbyte = qemu_host_page_size - nbyte;
- do {
- /* FIXME - what to do if put_user() fails? */
- put_user_u8(0, elf_bss);
- elf_bss++;
- } while (--nbyte);
+ last_bss = TARGET_PAGE_ALIGN(last_bss);
+
+ /* ??? There is confusion between qemu_real_host_page_size and
+ qemu_host_page_size here and elsewhere in target_mmap, which
+ may lead to the end of the data section mapping from the file
+ not being mapped. At least there was an explicit test and
+ comment for that here, suggesting that "the file size must
+ be known". The comment probably pre-dates the introduction
+ of the fstat system call in target_mmap which does in fact
+ find out the size. What isn't clear is if the workaround
+ here is still actually needed. For now, continue with it,
+ but merge it with the "normal" mmap that would allocate the bss. */
+
+ host_start = (uintptr_t) g2h(elf_bss);
+ host_end = (uintptr_t) g2h(last_bss);
+ host_map_start = (host_start + qemu_real_host_page_size - 1);
+ host_map_start &= -qemu_real_host_page_size;
+
+ if (host_map_start < host_end) {
+ void *p = mmap((void *)host_map_start, host_end - host_map_start,
+ prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (p == MAP_FAILED) {
+ perror("cannot mmap brk");
+ exit(-1);
}
-}
+ /* Since we didn't use target_mmap, make sure to record
+ the validity of the pages with qemu. */
+ page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
+ }
+
+ if (host_start < host_map_start) {
+ memset((void *)host_start, 0, host_map_start - host_start);
+ }
+}
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
- struct elfhdr * exec,
- abi_ulong load_addr,
- abi_ulong load_bias,
- abi_ulong interp_load_addr, int ibcs,
- struct image_info *info)
-{
- abi_ulong sp;
- int size;
- abi_ulong u_platform;
- const char *k_platform;
- const int n = sizeof(elf_addr_t);
-
- sp = p;
- u_platform = 0;
- k_platform = ELF_PLATFORM;
- if (k_platform) {
- size_t len = strlen(k_platform) + 1;
- sp -= (len + n - 1) & ~(n - 1);
- u_platform = sp;
- /* FIXME - check return value of memcpy_to_target() for failure */
- memcpy_to_target(sp, k_platform, len);
- }
- /*
- * Force 16 byte _final_ alignment here for generality.
- */
- sp = sp &~ (abi_ulong)15;
- size = (DLINFO_ITEMS + 1) * 2;
- if (k_platform)
- size += 2;
+ struct elfhdr *exec,
+ struct image_info *info,
+ struct image_info *interp_info)
+{
+ abi_ulong sp;
+ int size;
+ abi_ulong u_platform;
+ const char *k_platform;
+ const int n = sizeof(elf_addr_t);
+
+ sp = p;
+ u_platform = 0;
+ k_platform = ELF_PLATFORM;
+ if (k_platform) {
+ size_t len = strlen(k_platform) + 1;
+ sp -= (len + n - 1) & ~(n - 1);
+ u_platform = sp;
+ /* FIXME - check return value of memcpy_to_target() for failure */
+ memcpy_to_target(sp, k_platform, len);
+ }
+ /*
+ * Force 16 byte _final_ alignment here for generality.
+ */
+ sp = sp &~ (abi_ulong)15;
+ size = (DLINFO_ITEMS + 1) * 2;
+ if (k_platform)
+ size += 2;
#ifdef DLINFO_ARCH_ITEMS
- size += DLINFO_ARCH_ITEMS * 2;
+ size += DLINFO_ARCH_ITEMS * 2;
#endif
- size += envc + argc + 2;
- size += (!ibcs ? 3 : 1); /* argc itself */
- size *= n;
- if (size & 15)
- sp -= 16 - (size & 15);
-
- /* This is correct because Linux defines
- * elf_addr_t as Elf32_Off / Elf64_Off
- */
-#define NEW_AUX_ENT(id, val) do { \
- sp -= n; put_user_ual(val, sp); \
- sp -= n; put_user_ual(id, sp); \
- } while(0)
-
- NEW_AUX_ENT (AT_NULL, 0);
-
- /* There must be exactly DLINFO_ITEMS entries here. */
- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
- NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
- NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
- NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
- NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
- NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
- NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
- NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
- NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
- NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
- NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
- NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
- NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
- if (k_platform)
- NEW_AUX_ENT(AT_PLATFORM, u_platform);
+ size += envc + argc + 2;
+ size += 1; /* argc itself */
+ size *= n;
+ if (size & 15)
+ sp -= 16 - (size & 15);
+
+ /* This is correct because Linux defines
+ * elf_addr_t as Elf32_Off / Elf64_Off
+ */
+#define NEW_AUX_ENT(id, val) do { \
+ sp -= n; put_user_ual(val, sp); \
+ sp -= n; put_user_ual(id, sp); \
+ } while(0)
+
+ NEW_AUX_ENT (AT_NULL, 0);
+
+ /* There must be exactly DLINFO_ITEMS entries here. */
+ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
+ NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+ NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+ NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+ NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
+ NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
+ NEW_AUX_ENT(AT_ENTRY, info->entry);
+ NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+ NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+ NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+ NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+ NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
+ NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+ if (k_platform)
+ NEW_AUX_ENT(AT_PLATFORM, u_platform);
#ifdef ARCH_DLINFO
- /*
- * ARCH_DLINFO must come last so platform specific code can enforce
- * special alignment requirements on the AUXV if necessary (eg. PPC).
- */
- ARCH_DLINFO;
+ /*
+ * ARCH_DLINFO must come last so platform specific code can enforce
+ * special alignment requirements on the AUXV if necessary (eg. PPC).
+ */
+ ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT
- info->saved_auxv = sp;
+ info->saved_auxv = sp;
- sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
- return sp;
+ sp = loader_build_argptr(envc, argc, sp, p, 0);
+ return sp;
}
+/* Load an ELF image into the address space.
-static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
- int interpreter_fd,
- abi_ulong *interp_load_addr)
+ IMAGE_NAME is the filename of the image, to use in error messages.
+ IMAGE_FD is the open file descriptor for the image.
+
+ BPRM_BUF is a copy of the beginning of the file; this of course
+ contains the elf file header at offset 0. It is assumed that this
+ buffer is sufficiently aligned to present no problems to the host
+ in accessing data at aligned offsets within the buffer.
+
+ On return: INFO values will be filled in, as necessary or available. */
+
+static void load_elf_image(const char *image_name, int image_fd,
+ struct image_info *info, char **pinterp_name,
+ char bprm_buf[BPRM_BUF_SIZE])
{
- struct elf_phdr *elf_phdata = NULL;
- struct elf_phdr *eppnt;
- abi_ulong load_addr = 0;
- int load_addr_set = 0;
- int retval;
- abi_ulong last_bss, elf_bss;
- abi_ulong error;
- int i;
+ struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+ struct elf_phdr *phdr;
+ abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+ int i, retval;
+ const char *errmsg;
- elf_bss = 0;
- last_bss = 0;
- error = 0;
+ /* First of all, some simple consistency checks */
+ errmsg = "Invalid ELF image for this architecture";
+ if (!elf_check_ident(ehdr)) {
+ goto exit_errmsg;
+ }
+ bswap_ehdr(ehdr);
+ if (!elf_check_ehdr(ehdr)) {
+ goto exit_errmsg;
+ }
-#ifdef BSWAP_NEEDED
- bswap_ehdr(interp_elf_ex);
+ i = ehdr->e_phnum * sizeof(struct elf_phdr);
+ if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
+ phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
+ } else {
+ phdr = (struct elf_phdr *) alloca(i);
+ retval = pread(image_fd, phdr, i, ehdr->e_phoff);
+ if (retval != i) {
+ goto exit_read;
+ }
+ }
+ bswap_phdr(phdr, ehdr->e_phnum);
+
+ /* Find the maximum size of the image and allocate an appropriate
+ amount of memory to handle that. */
+ loaddr = -1, hiaddr = 0;
+ for (i = 0; i < ehdr->e_phnum; ++i) {
+ if (phdr[i].p_type == PT_LOAD) {
+ abi_ulong a = phdr[i].p_vaddr;
+ if (a < loaddr) {
+ loaddr = a;
+ }
+ a += phdr[i].p_memsz;
+ if (a > hiaddr) {
+ hiaddr = a;
+ }
+ }
+ }
+
+ load_addr = loaddr;
+ if (ehdr->e_type == ET_DYN) {
+ /* The image indicates that it can be loaded anywhere. Find a
+ location that can hold the memory space required. If the
+ image is pre-linked, LOADDR will be non-zero. Since we do
+ not supply MAP_FIXED here we'll use that address if and
+ only if it remains available. */
+ load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
+ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+ -1, 0);
+ if (load_addr == -1) {
+ goto exit_perror;
+ }
+ } else if (pinterp_name != NULL) {
+ /* This is the main executable. Make sure that the low
+ address does not conflict with MMAP_MIN_ADDR or the
+ QEMU application itself. */
+#if defined(CONFIG_USE_GUEST_BASE)
+ /*
+ * In case where user has not explicitly set the guest_base, we
+ * probe here that should we set it automatically.
+ */
+ if (!have_guest_base && !reserved_va) {
+ unsigned long host_start, real_start, host_size;
+
+ /* Round addresses to page boundaries. */
+ loaddr &= qemu_host_page_mask;
+ hiaddr = HOST_PAGE_ALIGN(hiaddr);
+
+ if (loaddr < mmap_min_addr) {
+ host_start = HOST_PAGE_ALIGN(mmap_min_addr);
+ } else {
+ host_start = loaddr;
+ if (host_start != loaddr) {
+ errmsg = "Address overflow loading ELF binary";
+ goto exit_errmsg;
+ }
+ }
+ host_size = hiaddr - loaddr;
+ while (1) {
+ /* Do not use mmap_find_vma here because that is limited to the
+ guest address space. We are going to make the
+ guest address space fit whatever we're given. */
+ real_start = (unsigned long)
+ mmap((void *)host_start, host_size, PROT_NONE,
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
+ if (real_start == (unsigned long)-1) {
+ goto exit_perror;
+ }
+ if (real_start == host_start) {
+ break;
+ }
+ /* That address didn't work. Unmap and try a different one.
+ The address the host picked because is typically right at
+ the top of the host address space and leaves the guest with
+ no usable address space. Resort to a linear search. We
+ already compensated for mmap_min_addr, so this should not
+ happen often. Probably means we got unlucky and host
+ address space randomization put a shared library somewhere
+ inconvenient. */
+ munmap((void *)real_start, host_size);
+ host_start += qemu_host_page_size;
+ if (host_start == loaddr) {
+ /* Theoretically possible if host doesn't have any suitably
+ aligned areas. Normally the first mmap will fail. */
+ errmsg = "Unable to find space for application";
+ goto exit_errmsg;
+ }
+ }
+ qemu_log("Relocating guest address space from 0x"
+ TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start);
+ guest_base = real_start - loaddr;
+ }
#endif
- /* First of all, some simple consistency checks */
- if ((interp_elf_ex->e_type != ET_EXEC &&
- interp_elf_ex->e_type != ET_DYN) ||
- !elf_check_arch(interp_elf_ex->e_machine)) {
- return ~((abi_ulong)0UL);
- }
+ }
+ load_bias = load_addr - loaddr;
+ info->load_bias = load_bias;
+ info->load_addr = load_addr;
+ info->entry = ehdr->e_entry + load_bias;
+ info->start_code = -1;
+ info->end_code = 0;
+ info->start_data = -1;
+ info->end_data = 0;
+ info->brk = 0;
- /* Now read in all of the header information */
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ struct elf_phdr *eppnt = phdr + i;
+ if (eppnt->p_type == PT_LOAD) {
+ abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
+ int elf_prot = 0;
- if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
- return ~(abi_ulong)0UL;
+ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
- elf_phdata = (struct elf_phdr *)
- malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+ vaddr = load_bias + eppnt->p_vaddr;
+ vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
+ vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
- if (!elf_phdata)
- return ~((abi_ulong)0UL);
+ error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+ elf_prot, MAP_PRIVATE | MAP_FIXED,
+ image_fd, eppnt->p_offset - vaddr_po);
+ if (error == -1) {
+ goto exit_perror;
+ }
- /*
- * If the size of this structure has changed, then punt, since
- * we will be doing the wrong thing.
- */
- if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
- free(elf_phdata);
- return ~((abi_ulong)0UL);
- }
+ vaddr_ef = vaddr + eppnt->p_filesz;
+ vaddr_em = vaddr + eppnt->p_memsz;
- retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
- if(retval >= 0) {
- retval = read(interpreter_fd,
- (char *) elf_phdata,
- sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
- }
- if (retval < 0) {
- perror("load_elf_interp");
- exit(-1);
- free (elf_phdata);
- return retval;
- }
-#ifdef BSWAP_NEEDED
- eppnt = elf_phdata;
- for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
- bswap_phdr(eppnt);
- }
-#endif
+ /* If the load segment requests extra zeros (e.g. bss), map it. */
+ if (vaddr_ef < vaddr_em) {
+ zero_bss(vaddr_ef, vaddr_em, elf_prot);
+ }
- if (interp_elf_ex->e_type == ET_DYN) {
- /* in order to avoid hardcoding the interpreter load
- address in qemu, we allocate a big enough memory zone */
- error = target_mmap(0, INTERP_MAP_SIZE,
- PROT_NONE, MAP_PRIVATE | MAP_ANON,
- -1, 0);
- if (error == -1) {
- perror("mmap");
- exit(-1);
+ /* Find the full program boundaries. */
+ if (elf_prot & PROT_EXEC) {
+ if (vaddr < info->start_code) {
+ info->start_code = vaddr;
+ }
+ if (vaddr_ef > info->end_code) {
+ info->end_code = vaddr_ef;
+ }
+ }
+ if (elf_prot & PROT_WRITE) {
+ if (vaddr < info->start_data) {
+ info->start_data = vaddr;
+ }
+ if (vaddr_ef > info->end_data) {
+ info->end_data = vaddr_ef;
+ }
+ if (vaddr_em > info->brk) {
+ info->brk = vaddr_em;
+ }
+ }
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
+ char *interp_name;
+
+ if (*pinterp_name) {
+ errmsg = "Multiple PT_INTERP entries";
+ goto exit_errmsg;
+ }
+ interp_name = malloc(eppnt->p_filesz);
+ if (!interp_name) {
+ goto exit_perror;
}
- load_addr = error;
- load_addr_set = 1;
+
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
+ eppnt->p_filesz);
+ } else {
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
+ eppnt->p_offset);
+ if (retval != eppnt->p_filesz) {
+ goto exit_perror;
+ }
+ }
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
+ errmsg = "Invalid PT_INTERP entry";
+ goto exit_errmsg;
+ }
+ *pinterp_name = interp_name;
}
+ }
+
+ if (info->end_data == 0) {
+ info->start_data = info->end_code;
+ info->end_data = info->end_code;
+ info->brk = info->end_code;
+ }
+
+ if (qemu_log_enabled()) {
+ load_symbols(ehdr, image_fd, load_bias);
+ }
+
+ close(image_fd);
+ return;
- eppnt = elf_phdata;
- for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
- if (eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
- int elf_prot = 0;
- abi_ulong vaddr = 0;
- abi_ulong k;
-
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
- elf_type |= MAP_FIXED;
- vaddr = eppnt->p_vaddr;
- }
- error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
- eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
- elf_prot,
- elf_type,
- interpreter_fd,
- eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
-
- if (error == -1) {
- /* Real error */
- close(interpreter_fd);
- free(elf_phdata);
- return ~((abi_ulong)0UL);
- }
-
- if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
- load_addr = error;
- load_addr_set = 1;
- }
-
- /*
- * Find the end of the file mapping for this phdr, and keep
- * track of the largest address we see for this.
- */
- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
- if (k > elf_bss) elf_bss = k;
-
- /*
- * Do the same thing for the memory mapping - between
- * elf_bss and last_bss is the bss section.
- */
- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
- if (k > last_bss) last_bss = k;
- }
-
- /* Now use mmap to map the library into memory. */
-
- close(interpreter_fd);
-
- /*
- * Now fill out the bss section. First pad the last page up
- * to the page boundary, and then perform a mmap to make sure
- * that there are zeromapped pages up to and including the last
- * bss page.
- */
- padzero(elf_bss, last_bss);
- elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
-
- /* Map the last of the bss segment */
- if (last_bss > elf_bss) {
- target_mmap(elf_bss, last_bss-elf_bss,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- }
- free(elf_phdata);
-
- *interp_load_addr = load_addr;
- return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+ exit_read:
+ if (retval >= 0) {
+ errmsg = "Incomplete read of file header";
+ goto exit_errmsg;
+ }
+ exit_perror:
+ errmsg = strerror(errno);
+ exit_errmsg:
+ fprintf(stderr, "%s: %s\n", image_name, errmsg);
+ exit(-1);
+}
+
+static void load_elf_interp(const char *filename, struct image_info *info,
+ char bprm_buf[BPRM_BUF_SIZE])
+{
+ int fd, retval;
+
+ fd = open(path(filename), O_RDONLY);
+ if (fd < 0) {
+ goto exit_perror;
+ }
+
+ retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+ if (retval < 0) {
+ goto exit_perror;
+ }
+ if (retval < BPRM_BUF_SIZE) {
+ memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+ }
+
+ load_elf_image(filename, fd, info, NULL, bprm_buf);
+ return;
+
+ exit_perror:
+ fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+ exit(-1);
}
static int symfind(const void *s0, const void *s1)
@@ -1371,88 +1475,97 @@ static int symcmp(const void *s0, const void *s1)
}
/* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd)
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
{
- unsigned int i, nsyms;
- struct elf_shdr sechdr, symtab, strtab;
+ int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
+ struct elf_shdr *shdr;
char *strings;
struct syminfo *s;
struct elf_sym *syms;
- lseek(fd, hdr->e_shoff, SEEK_SET);
- for (i = 0; i < hdr->e_shnum; i++) {
- if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
- return;
-#ifdef BSWAP_NEEDED
- bswap_shdr(&sechdr);
-#endif
- if (sechdr.sh_type == SHT_SYMTAB) {
- symtab = sechdr;
- lseek(fd, hdr->e_shoff
- + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
- if (read(fd, &strtab, sizeof(strtab))
- != sizeof(strtab))
- return;
-#ifdef BSWAP_NEEDED
- bswap_shdr(&strtab);
-#endif
+ shnum = hdr->e_shnum;
+ i = shnum * sizeof(struct elf_shdr);
+ shdr = (struct elf_shdr *)alloca(i);
+ if (pread(fd, shdr, i, hdr->e_shoff) != i) {
+ return;
+ }
+
+ bswap_shdr(shdr, shnum);
+ for (i = 0; i < shnum; ++i) {
+ if (shdr[i].sh_type == SHT_SYMTAB) {
+ sym_idx = i;
+ str_idx = shdr[i].sh_link;
goto found;
}
}
- return; /* Shouldn't happen... */
+
+ /* There will be no symbol table if the file was stripped. */
+ return;
found:
- /* Now know where the strtab and symtab are. Snarf them. */
+ /* Now know where the strtab and symtab are. Snarf them. */
s = malloc(sizeof(*s));
- syms = malloc(symtab.sh_size);
- if (!syms)
- return;
- s->disas_strtab = strings = malloc(strtab.sh_size);
- if (!s->disas_strtab)
+ if (!s) {
return;
+ }
- lseek(fd, symtab.sh_offset, SEEK_SET);
- if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+ i = shdr[str_idx].sh_size;
+ s->disas_strtab = strings = malloc(i);
+ if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
+ free(s);
+ free(strings);
return;
+ }
- nsyms = symtab.sh_size / sizeof(struct elf_sym);
+ i = shdr[sym_idx].sh_size;
+ syms = malloc(i);
+ if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
+ free(s);
+ free(strings);
+ free(syms);
+ return;
+ }
- i = 0;
- while (i < nsyms) {
-#ifdef BSWAP_NEEDED
+ nsyms = i / sizeof(struct elf_sym);
+ for (i = 0; i < nsyms; ) {
bswap_sym(syms + i);
-#endif
- // Throw away entries which we do not need.
- if (syms[i].st_shndx == SHN_UNDEF ||
- syms[i].st_shndx >= SHN_LORESERVE ||
- ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
- nsyms--;
- if (i < nsyms) {
+ /* Throw away entries which we do not need. */
+ if (syms[i].st_shndx == SHN_UNDEF
+ || syms[i].st_shndx >= SHN_LORESERVE
+ || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+ if (i < --nsyms) {
syms[i] = syms[nsyms];
}
- continue;
- }
+ } else {
#if defined(TARGET_ARM) || defined (TARGET_MIPS)
- /* The bottom address bit marks a Thumb or MIPS16 symbol. */
- syms[i].st_value &= ~(target_ulong)1;
+ /* The bottom address bit marks a Thumb or MIPS16 symbol. */
+ syms[i].st_value &= ~(target_ulong)1;
#endif
- i++;
+ syms[i].st_value += load_bias;
+ i++;
+ }
}
+
+ /* Attempt to free the storage associated with the local symbols
+ that we threw away. Whether or not this has any effect on the
+ memory allocation depends on the malloc implementation and how
+ many symbols we managed to discard. */
syms = realloc(syms, nsyms * sizeof(*syms));
+ if (syms == NULL) {
+ free(s);
+ free(strings);
+ return;
+ }
qsort(syms, nsyms, sizeof(*syms), symcmp);
- lseek(fd, strtab.sh_offset, SEEK_SET);
- if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
- return;
s->disas_num_syms = nsyms;
#if ELF_CLASS == ELFCLASS32
s->disas_symtab.elf32 = syms;
- s->lookup_symbol = lookup_symbolxx;
#else
s->disas_symtab.elf64 = syms;
- s->lookup_symbol = lookup_symbolxx;
#endif
+ s->lookup_symbol = lookup_symbolxx;
s->next = syminfos;
syminfos = s;
}
@@ -1460,477 +1573,67 @@ static void load_symbols(struct elfhdr *hdr, int fd)
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info)
{
+ struct image_info interp_info;
struct elfhdr elf_ex;
- struct elfhdr interp_elf_ex;
- struct exec interp_ex;
- int interpreter_fd = -1; /* avoid warning */
- abi_ulong load_addr, load_bias;
- int load_addr_set = 0;
- unsigned int interpreter_type = INTERPRETER_NONE;
- unsigned char ibcs2_interpreter;
- int i;
- abi_ulong mapped_addr;
- struct elf_phdr * elf_ppnt;
- struct elf_phdr *elf_phdata;
- abi_ulong elf_bss, k, elf_brk;
- int retval;
- char * elf_interpreter;
- abi_ulong elf_entry, interp_load_addr = 0;
- int status;
- abi_ulong start_code, end_code, start_data, end_data;
- abi_ulong reloc_func_desc = 0;
- abi_ulong elf_stack;
- char passed_fileno[6];
-
- ibcs2_interpreter = 0;
- status = 0;
- load_addr = 0;
- load_bias = 0;
- elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
-#ifdef BSWAP_NEEDED
- bswap_ehdr(&elf_ex);
-#endif
-
- /* First of all, some simple consistency checks */
- if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
- (! elf_check_arch(elf_ex.e_machine))) {
- return -ENOEXEC;
- }
-
- bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
- bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
- bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
- if (!bprm->p) {
- retval = -E2BIG;
- }
-
- /* Now read in all of the header information */
- elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
- if (elf_phdata == NULL) {
- return -ENOMEM;
- }
-
- retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
- if(retval > 0) {
- retval = read(bprm->fd, (char *) elf_phdata,
- elf_ex.e_phentsize * elf_ex.e_phnum);
- }
-
- if (retval < 0) {
- perror("load_elf_binary");
- exit(-1);
- free (elf_phdata);
- return -errno;
- }
-
-#ifdef BSWAP_NEEDED
- elf_ppnt = elf_phdata;
- for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
- bswap_phdr(elf_ppnt);
- }
-#endif
- elf_ppnt = elf_phdata;
-
- elf_bss = 0;
- elf_brk = 0;
-
-
- elf_stack = ~((abi_ulong)0UL);
- elf_interpreter = NULL;
- start_code = ~((abi_ulong)0UL);
- end_code = 0;
- start_data = 0;
- end_data = 0;
- interp_ex.a_info = 0;
-
- for(i=0;i < elf_ex.e_phnum; i++) {
- if (elf_ppnt->p_type == PT_INTERP) {
- if ( elf_interpreter != NULL )
- {
- free (elf_phdata);
- free(elf_interpreter);
- close(bprm->fd);
- return -EINVAL;
- }
-
- /* This is the program interpreter used for
- * shared libraries - for now assume that this
- * is an a.out format binary
- */
-
- elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
- if (elf_interpreter == NULL) {
- free (elf_phdata);
- close(bprm->fd);
- return -ENOMEM;
- }
-
- retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
- if(retval >= 0) {
- retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
- }
- if(retval < 0) {
- perror("load_elf_binary2");
- exit(-1);
- }
-
- /* If the program interpreter is one of these two,
- then assume an iBCS2 image. Otherwise assume
- a native linux image. */
-
- /* JRP - Need to add X86 lib dir stuff here... */
-
- if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
- strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
- ibcs2_interpreter = 1;
- }
+ char *elf_interpreter = NULL;
-#if 0
- printf("Using ELF interpreter %s\n", path(elf_interpreter));
-#endif
- if (retval >= 0) {
- retval = open(path(elf_interpreter), O_RDONLY);
- if(retval >= 0) {
- interpreter_fd = retval;
- }
- else {
- perror(elf_interpreter);
- exit(-1);
- /* retval = -errno; */
- }
- }
-
- if (retval >= 0) {
- retval = lseek(interpreter_fd, 0, SEEK_SET);
- if(retval >= 0) {
- retval = read(interpreter_fd,bprm->buf,128);
- }
- }
- if (retval >= 0) {
- interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
- interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
- }
- if (retval < 0) {
- perror("load_elf_binary3");
- exit(-1);
- free (elf_phdata);
- free(elf_interpreter);
- close(bprm->fd);
- return retval;
- }
- }
- elf_ppnt++;
- }
-
- /* Some simple consistency checks for the interpreter */
- if (elf_interpreter){
- interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
-
- /* Now figure out which format our binary is */
- if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
- (N_MAGIC(interp_ex) != QMAGIC)) {
- interpreter_type = INTERPRETER_ELF;
- }
-
- if (interp_elf_ex.e_ident[0] != 0x7f ||
- strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
- interpreter_type &= ~INTERPRETER_ELF;
- }
-
- if (!interpreter_type) {
- free(elf_interpreter);
- free(elf_phdata);
- close(bprm->fd);
- return -ELIBBAD;
- }
- }
-
- /* OK, we are done with that, now set up the arg stuff,
- and then start this sucker up */
-
- {
- char * passed_p;
-
- if (interpreter_type == INTERPRETER_AOUT) {
- snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
- passed_p = passed_fileno;
-
- if (elf_interpreter) {
- bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
- bprm->argc++;
- }
- }
- if (!bprm->p) {
- if (elf_interpreter) {
- free(elf_interpreter);
- }
- free (elf_phdata);
- close(bprm->fd);
- return -E2BIG;
- }
- }
-
- /* OK, This is the point of no return */
- info->end_data = 0;
- info->end_code = 0;
info->start_mmap = (abi_ulong)ELF_START_MMAP;
info->mmap = 0;
- elf_entry = (abi_ulong) elf_ex.e_entry;
+ info->rss = 0;
-#if defined(CONFIG_USE_GUEST_BASE)
- /*
- * In case where user has not explicitly set the guest_base, we
- * probe here that should we set it automatically.
- */
- if (!(have_guest_base || reserved_va)) {
- /*
- * Go through ELF program header table and find the address
- * range used by loadable segments. Check that this is available on
- * the host, and if not find a suitable value for guest_base. */
- abi_ulong app_start = ~0;
- abi_ulong app_end = 0;
- abi_ulong addr;
- unsigned long host_start;
- unsigned long real_start;
- unsigned long host_size;
- for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
- i++, elf_ppnt++) {
- if (elf_ppnt->p_type != PT_LOAD)
- continue;
- addr = elf_ppnt->p_vaddr;
- if (addr < app_start) {
- app_start = addr;
- }
- addr += elf_ppnt->p_memsz;
- if (addr > app_end) {
- app_end = addr;
- }
- }
+ load_elf_image(bprm->filename, bprm->fd, info,
+ &elf_interpreter, bprm->buf);
- /* If we don't have any loadable segments then something
- is very wrong. */
- assert(app_start < app_end);
+ /* ??? We need a copy of the elf header for passing to create_elf_tables.
+ If we do nothing, we'll have overwritten this when we re-use bprm->buf
+ when we load the interpreter. */
+ elf_ex = *(struct elfhdr *)bprm->buf;
- /* Round addresses to page boundaries. */
- app_start = app_start & qemu_host_page_mask;
- app_end = HOST_PAGE_ALIGN(app_end);
- if (app_start < mmap_min_addr) {
- host_start = HOST_PAGE_ALIGN(mmap_min_addr);
- } else {
- host_start = app_start;
- if (host_start != app_start) {
- fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
- abort();
- }
- }
- host_size = app_end - app_start;
- while (1) {
- /* Do not use mmap_find_vma here because that is limited to the
- guest address space. We are going to make the
- guest address space fit whatever we're given. */
- real_start = (unsigned long)mmap((void *)host_start, host_size,
- PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
- if (real_start == (unsigned long)-1) {
- fprintf(stderr, "qemu: Virtual memory exausted\n");
- abort();
- }
- if (real_start == host_start) {
- break;
- }
- /* That address didn't work. Unmap and try a different one.
- The address the host picked because is typically
- right at the top of the host address space and leaves the
- guest with no usable address space. Resort to a linear search.
- We already compensated for mmap_min_addr, so this should not
- happen often. Probably means we got unlucky and host address
- space randomization put a shared library somewhere
- inconvenient. */
- munmap((void *)real_start, host_size);
- host_start += qemu_host_page_size;
- if (host_start == app_start) {
- /* Theoretically possible if host doesn't have any
- suitably aligned areas. Normally the first mmap will
- fail. */
- fprintf(stderr, "qemu: Unable to find space for application\n");
- abort();
- }
- }
- qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
- " to 0x%lx\n", app_start, real_start);
- guest_base = real_start - app_start;
+ bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
+ bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
+ bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
+ if (!bprm->p) {
+ fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
+ exit(-1);
}
-#endif /* CONFIG_USE_GUEST_BASE */
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
- info->rss = 0;
bprm->p = setup_arg_pages(bprm->p, bprm, info);
- info->start_stack = bprm->p;
- /* Now we do a little grungy work by mmaping the ELF image into
- * the correct location in memory. At this point, we assume that
- * the image should be loaded at fixed address, not at a variable
- * address.
- */
+ if (elf_interpreter) {
+ load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
- for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
- int elf_prot = 0;
- int elf_flags = 0;
- abi_ulong error;
+ /* If the program interpreter is one of these two, then assume
+ an iBCS2 image. Otherwise assume a native linux image. */
- if (elf_ppnt->p_type != PT_LOAD)
- continue;
+ if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
+ || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
+ info->personality = PER_SVR4;
- if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
- if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
- if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
- elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
- if (elf_ex.e_type == ET_EXEC || load_addr_set) {
- elf_flags |= MAP_FIXED;
- } else if (elf_ex.e_type == ET_DYN) {
- /* Try and get dynamic programs out of the way of the default mmap
- base, as well as whatever program they might try to exec. This
- is because the brk will follow the loader, and is not movable. */
- /* NOTE: for qemu, we do a big mmap to get enough space
- without hardcoding any address */
- error = target_mmap(0, ET_DYN_MAP_SIZE,
- PROT_NONE, MAP_PRIVATE | MAP_ANON,
- -1, 0);
- if (error == -1) {
- perror("mmap");
- exit(-1);
- }
- load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
+ /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
+ and some applications "depend" upon this behavior. Since
+ we do not have the power to recompile these, we emulate
+ the SVr4 behavior. Sigh. */
+ target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE, -1, 0);
}
-
- error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
- (elf_ppnt->p_filesz +
- TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
- elf_prot,
- (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
- bprm->fd,
- (elf_ppnt->p_offset -
- TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
- if (error == -1) {
- perror("mmap");
- exit(-1);
- }
-
-#ifdef LOW_ELF_STACK
- if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
- elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
-#endif
-
- if (!load_addr_set) {
- load_addr_set = 1;
- load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
- if (elf_ex.e_type == ET_DYN) {
- load_bias += error -
- TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
- load_addr += load_bias;
- reloc_func_desc = load_bias;
- }
- }
- k = elf_ppnt->p_vaddr;
- if (k < start_code)
- start_code = k;
- if (start_data < k)
- start_data = k;
- k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
- if (k > elf_bss)
- elf_bss = k;
- if ((elf_ppnt->p_flags & PF_X) && end_code < k)
- end_code = k;
- if (end_data < k)
- end_data = k;
- k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
- if (k > elf_brk) elf_brk = k;
- }
-
- elf_entry += load_bias;
- elf_bss += load_bias;
- elf_brk += load_bias;
- start_code += load_bias;
- end_code += load_bias;
- start_data += load_bias;
- end_data += load_bias;
-
- if (elf_interpreter) {
- if (interpreter_type & 1) {
- elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
- }
- else if (interpreter_type & 2) {
- elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
- &interp_load_addr);
- }
- reloc_func_desc = interp_load_addr;
-
- close(interpreter_fd);
- free(elf_interpreter);
-
- if (elf_entry == ~((abi_ulong)0UL)) {
- printf("Unable to load interpreter\n");
- free(elf_phdata);
- exit(-1);
- return 0;
- }
}
- free(elf_phdata);
-
- if (qemu_log_enabled())
- load_symbols(&elf_ex, bprm->fd);
-
- if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
- info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
-
-#ifdef LOW_ELF_STACK
- info->start_stack = bprm->p = elf_stack - 4;
-#endif
- bprm->p = create_elf_tables(bprm->p,
- bprm->argc,
- bprm->envc,
- &elf_ex,
- load_addr, load_bias,
- interp_load_addr,
- (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
- info);
- info->load_addr = reloc_func_desc;
- info->start_brk = info->brk = elf_brk;
- info->end_code = end_code;
- info->start_code = start_code;
- info->start_data = start_data;
- info->end_data = end_data;
+ bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+ info, (elf_interpreter ? &interp_info : NULL));
info->start_stack = bprm->p;
- /* Calling set_brk effectively mmaps the pages that we need for the bss and break
- sections */
- set_brk(elf_bss, elf_brk);
-
- padzero(elf_bss, elf_brk);
-
-#if 0
- printf("(start_brk) %x\n" , info->start_brk);
- printf("(end_code) %x\n" , info->end_code);
- printf("(start_code) %x\n" , info->start_code);
- printf("(end_data) %x\n" , info->end_data);
- printf("(start_stack) %x\n" , info->start_stack);
- printf("(brk) %x\n" , info->brk);
-#endif
-
- if ( info->personality == PER_SVR4 )
- {
- /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
- and some applications "depend" upon this behavior.
- Since we do not have the power to recompile these, we
- emulate the SVr4 behavior. Sigh. */
- mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, -1, 0);
+ /* If we have an interpreter, set that as the program's entry point.
+ Copy the load_addr as well, to help PPC64 interpret the entry
+ point as a function descriptor. Do this after creating elf tables
+ so that we copy the original program entry point into the AUXV. */
+ if (elf_interpreter) {
+ info->load_addr = interp_info.load_addr;
+ info->entry = interp_info.entry;
+ free(elf_interpreter);
}
- info->entry = elf_entry;
-
#ifdef USE_ELF_CORE_DUMP
bprm->core_dump = &elf_core_dump;
#endif
@@ -1939,7 +1642,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
}
#ifdef USE_ELF_CORE_DUMP
-
/*
* Definitions to generate Intel SVR4-like core files.
* These mostly have the same names as the SVR4 types with "target_elf_"
@@ -2076,17 +1778,17 @@ struct mm_struct {
static struct mm_struct *vma_init(void);
static void vma_delete(struct mm_struct *);
static int vma_add_mapping(struct mm_struct *, abi_ulong,
- abi_ulong, abi_ulong);
+ abi_ulong, abi_ulong);
static int vma_get_mapping_count(const struct mm_struct *);
static struct vm_area_struct *vma_first(const struct mm_struct *);
static struct vm_area_struct *vma_next(struct vm_area_struct *);
static abi_ulong vma_dump_size(const struct vm_area_struct *);
static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
- unsigned long flags);
+ unsigned long flags);
static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
static void fill_note(struct memelfnote *, const char *, int,
- unsigned int, void *);
+ unsigned int, void *);
static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
static void fill_auxv_note(struct memelfnote *, const TaskState *);
@@ -2102,9 +1804,6 @@ static int write_note(struct memelfnote *, int);
static int write_note_info(struct elf_note_info *, int);
#ifdef BSWAP_NEEDED
-static void bswap_prstatus(struct target_elf_prstatus *);
-static void bswap_psinfo(struct target_elf_prpsinfo *);
-
static void bswap_prstatus(struct target_elf_prstatus *prstatus)
{
prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
@@ -2132,6 +1831,17 @@ static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
psinfo->pr_sid = tswap32(psinfo->pr_sid);
}
+
+static void bswap_note(struct elf_note *en)
+{
+ bswap32s(&en->n_namesz);
+ bswap32s(&en->n_descsz);
+ bswap32s(&en->n_type);
+}
+#else
+static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
+static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
+static inline void bswap_note(struct elf_note *en) { }
#endif /* BSWAP_NEEDED */
/*
@@ -2166,7 +1876,7 @@ static void vma_delete(struct mm_struct *mm)
}
static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
- abi_ulong end, abi_ulong flags)
+ abi_ulong end, abi_ulong flags)
{
struct vm_area_struct *vma;
@@ -2235,7 +1945,7 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
}
static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
- unsigned long flags)
+ unsigned long flags)
{
struct mm_struct *mm = (struct mm_struct *)priv;
@@ -2244,7 +1954,7 @@ static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
}
static void fill_note(struct memelfnote *note, const char *name, int type,
- unsigned int sz, void *data)
+ unsigned int sz, void *data)
{
unsigned int namesz;
@@ -2265,7 +1975,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
}
static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
- uint32_t flags)
+ uint32_t flags)
{
(void) memset(elf, 0, sizeof(*elf));
@@ -2284,9 +1994,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
elf->e_phentsize = sizeof(struct elf_phdr);
elf->e_phnum = segs;
-#ifdef BSWAP_NEEDED
bswap_ehdr(elf);
-#endif
}
static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
@@ -2300,9 +2008,7 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
phdr->p_flags = 0;
phdr->p_align = 0;
-#ifdef BSWAP_NEEDED
- bswap_phdr(phdr);
-#endif
+ bswap_phdr(phdr, 1);
}
static size_t note_size(const struct memelfnote *note)
@@ -2311,7 +2017,7 @@ static size_t note_size(const struct memelfnote *note)
}
static void fill_prstatus(struct target_elf_prstatus *prstatus,
- const TaskState *ts, int signr)
+ const TaskState *ts, int signr)
{
(void) memset(prstatus, 0, sizeof (*prstatus));
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
@@ -2320,9 +2026,7 @@ static void fill_prstatus(struct target_elf_prstatus *prstatus,
prstatus->pr_pgrp = getpgrp();
prstatus->pr_sid = getsid(0);
-#ifdef BSWAP_NEEDED
bswap_prstatus(prstatus);
-#endif
}
static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
@@ -2352,13 +2056,11 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
filename = strdup(ts->bprm->filename);
base_filename = strdup(basename(filename));
(void) strncpy(psinfo->pr_fname, base_filename,
- sizeof(psinfo->pr_fname));
+ sizeof(psinfo->pr_fname));
free(base_filename);
free(filename);
-#ifdef BSWAP_NEEDED
bswap_psinfo(psinfo);
-#endif
return (0);
}
@@ -2401,7 +2103,7 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
* Returns 0 in case of success, -1 otherwise (errno is set).
*/
static int core_dump_filename(const TaskState *ts, char *buf,
- size_t bufsize)
+ size_t bufsize)
{
char timestamp[64];
char *filename = NULL;
@@ -2413,16 +2115,16 @@ static int core_dump_filename(const TaskState *ts, char *buf,
if (gettimeofday(&tv, NULL) < 0) {
(void) fprintf(stderr, "unable to get current timestamp: %s",
- strerror(errno));
+ strerror(errno));
return (-1);
}
filename = strdup(ts->bprm->filename);
base_filename = strdup(basename(filename));
(void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
- localtime_r(&tv.tv_sec, &tm));
+ localtime_r(&tv.tv_sec, &tm));
(void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
- base_filename, timestamp, (int)getpid());
+ base_filename, timestamp, (int)getpid());
free(base_filename);
free(filename);
@@ -2483,9 +2185,7 @@ static int write_note(struct memelfnote *men, int fd)
en.n_type = men->type;
en.n_descsz = men->datasz;
-#ifdef BSWAP_NEEDED
bswap_note(&en);
-#endif
if (dump_write(fd, &en, sizeof(en)) != 0)
return (-1);
@@ -2507,7 +2207,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
fill_prstatus(&ets->prstatus, ts, 0);
elf_core_copy_regs(&ets->prstatus.pr_reg, env);
fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
- &ets->prstatus);
+ &ets->prstatus);
QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
@@ -2515,7 +2215,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
}
static int fill_note_info(struct elf_note_info *info,
- long signr, const CPUState *env)
+ long signr, const CPUState *env)
{
#define NUMNOTES 3
CPUState *cpu = NULL;
@@ -2543,10 +2243,10 @@ static int fill_note_info(struct elf_note_info *info,
fill_prstatus(info->prstatus, ts, signr);
elf_core_copy_regs(&info->prstatus->pr_reg, env);
fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
- sizeof (*info->prstatus), info->prstatus);
+ sizeof (*info->prstatus), info->prstatus);
fill_psinfo(info->psinfo, ts);
fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
- sizeof (*info->psinfo), info->psinfo);
+ sizeof (*info->psinfo), info->psinfo);
fill_auxv_note(&info->notes[2], ts);
info->numnote = 3;
@@ -2593,7 +2293,7 @@ static int write_note_info(struct elf_note_info *info, int fd)
/* write prstatus for each thread */
for (ets = info->thread_list.tqh_first; ets != NULL;
- ets = ets->ets_link.tqe_next) {
+ ets = ets->ets_link.tqe_next) {
if ((error = write_note(&ets->notes[0], fd)) != 0)
return (error);
}
@@ -2661,13 +2361,13 @@ static int elf_core_dump(int signr, const CPUState *env)
errno = 0;
getrlimit(RLIMIT_CORE, &dumpsize);
if (dumpsize.rlim_cur == 0)
- return 0;
+ return 0;
if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
return (-errno);
if ((fd = open(corefile, O_WRONLY | O_CREAT,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
return (-errno);
/*
@@ -2756,7 +2456,7 @@ static int elf_core_dump(int signr, const CPUState *env)
end = vma->vma_start + vma_dump_size(vma);
for (addr = vma->vma_start; addr < end;
- addr += TARGET_PAGE_SIZE) {
+ addr += TARGET_PAGE_SIZE) {
char page[TARGET_PAGE_SIZE];
int error;
@@ -2767,7 +2467,7 @@ static int elf_core_dump(int signr, const CPUState *env)
error = copy_from_user(page, addr, sizeof (page));
if (error != 0) {
(void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
- addr);
+ addr);
errno = -error;
goto out;
}
@@ -2776,7 +2476,7 @@ static int elf_core_dump(int signr, const CPUState *env)
}
}
-out:
+ out:
free_note_info(&info);
if (mm != NULL)
vma_delete(mm);
@@ -2786,15 +2486,8 @@ out:
return (-errno);
return (0);
}
-
#endif /* USE_ELF_CORE_DUMP */
-static int load_aout_interp(void * exptr, int interp_fd)
-{
- printf("a.out interpreter not yet supported\n");
- return(0);
-}
-
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
init_thread(regs, infop);
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 13ad9aaeb..9ee27c355 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -96,18 +96,16 @@ static int prepare_binprm(struct linux_binprm *bprm)
}
}
- retval = lseek(bprm->fd, 0L, SEEK_SET);
- if(retval >= 0) {
- retval = read(bprm->fd, bprm->buf, 128);
- }
- if(retval < 0) {
+ retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+ if (retval < 0) {
perror("prepare_binprm");
exit(-1);
- /* return(-errno); */
}
- else {
- return(retval);
+ if (retval < BPRM_BUF_SIZE) {
+ /* Make sure the rest of the loader won't read garbage. */
+ memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
}
+ return retval;
}
/* Construct the envp and argv tables on the target stack. */
@@ -163,8 +161,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
int i;
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
- for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
- bprm->page[i] = NULL;
+ memset(bprm->page, 0, sizeof(bprm->page));
retval = open(filename, O_RDONLY);
if (retval < 0)
return retval;
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 39da6dfb4..e10a6ef2e 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -225,13 +225,13 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
int prot;
int looped = 0;
- if (size > reserved_va) {
+ if (size > RESERVED_VA) {
return (abi_ulong)-1;
}
last_addr = start;
for (addr = start; last_addr + size != addr; addr += qemu_host_page_size) {
- if (last_addr + size >= reserved_va
+ if (last_addr + size >= RESERVED_VA
|| (abi_ulong)(last_addr + size) < last_addr) {
if (looped) {
return (abi_ulong)-1;
@@ -271,7 +271,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
size = HOST_PAGE_ALIGN(size);
- if (reserved_va) {
+ if (RESERVED_VA) {
return mmap_find_vma_reserved(start, size);
}
@@ -651,7 +651,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
ret = 0;
/* unmap what we can */
if (real_start < real_end) {
- if (reserved_va) {
+ if (RESERVED_VA) {
mmap_reserve(real_start, real_end - real_start);
} else {
ret = munmap(g2h(real_start), real_end - real_start);
@@ -679,7 +679,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
flags,
g2h(new_addr));
- if (reserved_va && host_addr != MAP_FAILED) {
+ if (RESERVED_VA && host_addr != MAP_FAILED) {
/* If new and old addresses overlap then the above mremap will
already have failed with EINVAL. */
mmap_reserve(old_addr, old_size);
@@ -701,7 +701,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
}
} else {
int prot = 0;
- if (reserved_va && old_size < new_size) {
+ if (RESERVED_VA && old_size < new_size) {
abi_ulong addr;
for (addr = old_addr + old_size;
addr < old_addr + new_size;
@@ -711,7 +711,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
}
if (prot == 0) {
host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
- if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) {
+ if (host_addr != MAP_FAILED && RESERVED_VA && old_size > new_size) {
mmap_reserve(old_addr + old_size, new_size - old_size);
}
} else {
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 1878d5a61..794fe4913 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -31,6 +31,7 @@
* task_struct fields in the kernel
*/
struct image_info {
+ abi_ulong load_bias;
abi_ulong load_addr;
abi_ulong start_code;
abi_ulong end_code;
@@ -144,12 +145,16 @@ extern unsigned long mmap_min_addr;
*/
#define MAX_ARG_PAGES 33
+/* Read a good amount of data initially, to hopefully get all the
+ program headers loaded. */
+#define BPRM_BUF_SIZE 1024
+
/*
* This structure is used to hold the arguments that are
* used when loading binaries.
*/
struct linux_binprm {
- char buf[128];
+ char buf[BPRM_BUF_SIZE] __attribute__((aligned));
void *page[MAX_ARG_PAGES];
abi_ulong p;
int fd;
diff --git a/migration.c b/migration.c
index 650eb78d2..a160462df 100644
--- a/migration.c
+++ b/migration.c
@@ -67,6 +67,8 @@ void process_incoming_migration(QEMUFile *f)
qemu_announce_self();
DPRINTF("successfully loaded vm state\n");
+ incoming_expected = false;
+
if (autostart)
vm_start();
}
diff --git a/monitor.c b/monitor.c
index e51df62d6..0141a65ea 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1082,6 +1082,10 @@ static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
struct bdrv_iterate_context context = { mon, 0 };
+ if (incoming_expected) {
+ qerror_report(QERR_MIGRATION_EXPECTED);
+ return -1;
+ }
bdrv_iterate(encrypted_bdrv_it, &context);
/* only resume the vm if all keys are set and valid */
if (!context.err) {
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 50d127ad3..4ac61d2ad 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -38,6 +38,7 @@
#include <net/if.h>
#include <syslog.h>
#include <stropts.h>
+#include "qemu-error.h"
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
{
diff --git a/qemu-io.c b/qemu-io.c
index 7c6120b6a..2dbe20f33 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -135,7 +135,7 @@ create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
for (i = 0; i < nr_iov; i++) {
char *arg = argv[i];
- uint64_t len;
+ int64_t len;
len = cvtnum(arg);
if (len < 0) {
@@ -144,7 +144,7 @@ create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
}
/* should be SIZE_T_MAX, but that doesn't exist */
- if (len > UINT_MAX) {
+ if (len > INT_MAX) {
printf("too large length argument -- %s\n", arg);
goto fail;
}
diff --git a/qemu-options.hx b/qemu-options.hx
index a0e3059fd..66c84a0b7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -118,7 +118,7 @@ ETEXI
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
- " [,cache=writethrough|writeback|unsafe|none][,format=f]\n"
+ " [,cache=writethrough|writeback|none|unsafe][,format=f]\n"
" [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
" [,readonly=on|off][,boot=on|off]\n"
" use 'file' as a drive image\n", QEMU_ARCH_ALL)
diff --git a/qerror.c b/qerror.c
index 2f6f59061..0af3ab32b 100644
--- a/qerror.c
+++ b/qerror.c
@@ -141,6 +141,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Using KVM without %(capability), %(feature) unavailable",
},
{
+ .error_fmt = QERR_MIGRATION_EXPECTED,
+ .desc = "An incoming migration is expected before this command can be executed",
+ },
+ {
.error_fmt = QERR_MISSING_PARAMETER,
.desc = "Parameter '%(name)' is missing",
},
diff --git a/qerror.h b/qerror.h
index 9ad00b4b8..62802ea08 100644
--- a/qerror.h
+++ b/qerror.h
@@ -121,6 +121,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
+#define QERR_MIGRATION_EXPECTED \
+ "{ 'class': 'MigrationExpected', 'data': {} }"
+
#define QERR_MISSING_PARAMETER \
"{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
diff --git a/savevm.c b/savevm.c
index 459a3aaf2..681f0fb61 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1162,6 +1162,9 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
QTAILQ_REMOVE(&savevm_handlers, se, entry);
+ if (se->compat) {
+ qemu_free(se->compat);
+ }
qemu_free(se);
}
}
@@ -1229,6 +1232,9 @@ void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
if (se->vmsd == vmsd && se->opaque == opaque) {
QTAILQ_REMOVE(&savevm_handlers, se, entry);
+ if (se->compat) {
+ qemu_free(se->compat);
+ }
qemu_free(se);
}
}
diff --git a/sysemu.h b/sysemu.h
index bf1d68add..98bd47da3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -100,6 +100,7 @@ typedef enum DisplayType
} DisplayType;
extern int autostart;
+extern int incoming_expected;
extern int bios_size;
typedef enum {
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index a619b7261..50c65bdc3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1359,8 +1359,7 @@ void helper_mtc0_cause (target_ulong arg1)
void helper_mtc0_ebase (target_ulong arg1)
{
/* vectored interrupts not implemented */
- /* Multi-CPU not implemented */
- env->CP0_EBase = 0x80000000 | (arg1 & 0x3FFFF000);
+ env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
}
void helper_mtc0_config0 (target_ulong arg1)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 6c72dee1b..20b66a8a5 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12679,8 +12679,7 @@ void cpu_reset (CPUMIPSState *env)
env->CP0_Random = env->tlb->nb_tlb - 1;
env->tlb->tlb_in_use = env->tlb->nb_tlb;
env->CP0_Wired = 0;
- /* SMP not implemented */
- env->CP0_EBase = 0x80000000;
+ env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
/* vectored interrupts not implemented, timer on int 7,
no performance counters. */
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 0d9899e1b..8d1ece704 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -45,10 +45,6 @@
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
(0 << CP0C3_SM) | (0 << CP0C3_TL))
-/* Define a implementation number of 1.
- Define a major version 1, minor version 0. */
-#define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
-
/* MMU types, the first four entries have the same layout as the
CP0C0_MT field. */
enum mips_mmu_types {
diff --git a/tests/cris/check_addo.c b/tests/cris/check_addo.c
index 8a0565a1a..3d8e789f5 100644
--- a/tests/cris/check_addo.c
+++ b/tests/cris/check_addo.c
@@ -85,7 +85,7 @@ int main(void)
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_pi_b(p, t);
- cris_tst_cc(1, 1, 1, 1);
+ cris_tst_cc(0, 0, 0, 0);
asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
if (*(uint16_t*)r != 0xff22)
err();
@@ -114,7 +114,7 @@ int main(void)
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_pi_d(p, t);
- cris_tst_cc(1, 1, 1, 1);
+ cris_tst_cc(0, 0, 0, 0);
asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
r = (void*)(((char *)r) + 76789885);
if (*r != 0x55aa77ff)
diff --git a/tests/cris/check_addoq.c b/tests/cris/check_addoq.c
index b8b15c309..ed509e27e 100644
--- a/tests/cris/check_addoq.c
+++ b/tests/cris/check_addoq.c
@@ -27,7 +27,7 @@ int main(void)
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addoq(4, t);
- cris_tst_cc(1, 1, 1, 1);
+ cris_tst_cc(0, 0, 0, 0);
asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
if (*p != 0x88ccee19)
err();
diff --git a/tests/cris/check_settls1.c b/tests/cris/check_settls1.c
index 0ed99cf4c..69d202652 100644
--- a/tests/cris/check_settls1.c
+++ b/tests/cris/check_settls1.c
@@ -11,11 +11,15 @@
int main (void)
{
- unsigned long tp;
+ unsigned long tp, old_tp;
int ret;
+ asm volatile ("move $pid,%0" : "=r" (old_tp));
+ old_tp &= ~0xff;
+
ret = syscall (SYS_set_thread_area, 0xf0);
if (ret != -1 || errno != EINVAL) {
+ syscall (SYS_set_thread_area, old_tp);
perror ("Invalid thread area accepted:");
abort();
}
@@ -26,10 +30,12 @@ int main (void)
abort ();
}
- asm ("move $pid,%0" : "=r" (tp));
+ asm volatile ("move $pid,%0" : "=r" (tp));
tp &= ~0xff;
+ syscall (SYS_set_thread_area, old_tp);
if (tp != 0xeddeed00) {
+ * (volatile int *) 0 = 0;
perror ("tls2");
abort ();
}
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 86bb49a16..c4c9c3bcc 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -111,16 +111,16 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h)
* compression (by applying "gradient" filter or JPEG coder).
*/
-static uint
+static unsigned int
tight_detect_smooth_image24(VncState *vs, int w, int h)
{
int off;
int x, y, d, dx;
- uint c;
- uint stats[256];
+ unsigned int c;
+ unsigned int stats[256];
int pixels = 0;
int pix, left[3];
- uint errors;
+ unsigned int errors;
unsigned char *buf = vs->tight.tight.buffer;
/*
@@ -177,17 +177,17 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
#define DEFINE_DETECT_FUNCTION(bpp) \
\
- static uint \
+ static unsigned int \
tight_detect_smooth_image##bpp(VncState *vs, int w, int h) { \
bool endian; \
uint##bpp##_t pix; \
int max[3], shift[3]; \
int x, y, d, dx; \
- uint c; \
- uint stats[256]; \
+ unsigned int c; \
+ unsigned int stats[256]; \
int pixels = 0; \
int sample, sum, left[3]; \
- uint errors; \
+ unsigned int errors; \
unsigned char *buf = vs->tight.tight.buffer; \
\
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
@@ -267,7 +267,7 @@ DEFINE_DETECT_FUNCTION(32)
static int
tight_detect_smooth_image(VncState *vs, int w, int h)
{
- uint errors;
+ unsigned int errors;
int compression = vs->tight.compression;
int quality = vs->tight.quality;
@@ -281,7 +281,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
return 0;
}
- if (vs->tight.quality != -1) {
+ if (vs->tight.quality != (uint8_t)-1) {
if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) {
return 0;
}
@@ -294,7 +294,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
if (vs->clientds.pf.bytes_per_pixel == 4) {
if (vs->tight.pixel24) {
errors = tight_detect_smooth_image24(vs, w, h);
- if (vs->tight.quality != -1) {
+ if (vs->tight.quality != (uint8_t)-1) {
return (errors < tight_conf[quality].jpeg_threshold24);
}
return (errors < tight_conf[compression].gradient_threshold24);
@@ -443,7 +443,7 @@ static int tight_fill_palette(VncState *vs, int x, int y,
* Should never happen, but don't break everything \
* if it does, use the first color instead \
*/ \
- if (idx == -1) { \
+ if (idx == (uint8_t)-1) { \
idx = 0; \
} \
while (rep >= 0) { \
@@ -1469,6 +1469,8 @@ static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h,
ret = send_mono_rect(vs, x, y, w, h, bg, fg);
} else if (colors <= 256) {
ret = send_palette_rect(vs, x, y, w, h, palette);
+ } else {
+ ret = 0;
}
return ret;
}
@@ -1501,6 +1503,8 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h,
} else {
ret = send_palette_rect(vs, x, y, w, h, palette);
}
+ } else {
+ ret = 0;
}
return ret;
}
@@ -1522,7 +1526,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
colors = tight_fill_palette(vs, x, y, w * h, &fg, &bg, &palette);
#ifdef CONFIG_VNC_JPEG
- if (vs->tight.quality != -1) {
+ if (vs->tight.quality != (uint8_t)-1) {
ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, palette);
} else {
ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, palette);
diff --git a/vl.c b/vl.c
index cbe1097c8..468dbac83 100644
--- a/vl.c
+++ b/vl.c
@@ -183,6 +183,7 @@ int nb_nics;
NICInfo nd_table[MAX_NICS];
int vm_running;
int autostart;
+int incoming_expected; /* Started with -incoming and waiting for incoming */
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
@@ -807,9 +808,7 @@ static void smp_parse(const char *optarg)
threads = threads > 0 ? threads : 1;
cores = smp / (sockets * threads);
} else {
- if (sockets) {
- threads = smp / (cores * sockets);
- }
+ threads = smp / (cores * sockets);
}
}
smp_cpus = smp;
@@ -2625,6 +2624,7 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_incoming:
incoming = optarg;
+ incoming_expected = true;
break;
case QEMU_OPTION_nodefaults:
default_serial = 0;