aboutsummaryrefslogtreecommitdiff
path: root/config
AgeCommit message (Expand)AuthorFilesLines
2007-02-092007-02-09 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini4-10/+112
2007-02-09 * Makefile.tpl (build_alias, host_alias, target_alias): UseDaniel Jacobowitz2-1/+6
2007-02-052007-02-05 Dave Brolley <brolley@redhat.com>Dave Brolley2-0/+12
2007-01-142007-01-14 H.J. Lu <hongjiu.lu@intel.com>H.J. Lu2-2/+51
2007-01-112007-01-11 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-12/+22
2007-01-112007-01-11 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-11/+20
2007-01-022007-01-01 Mike Stump <mrs@apple.com>Paolo Bonzini2-8/+2
2006-12-292006-12-29 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-1/+6
2006-12-192006-12-19 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini3-4/+16
2006-12-11 * configure.in: Handle spu makefile frag.Alan Modra1-0/+2
2006-11-14 * tls.m4 (GCC_CHECK_TLS): Fall back to a link test.Daniel Jacobowitz2-1/+6
2006-11-14Merge ChangeLog and multi.m4 from GCC repository.Geoffrey Keating2-11/+79
2006-10-02 * tls.m4 (GCC_CHECK_TLS): Pass empty argument as "help arg" toTom Tromey2-1/+6
2006-07-25Sync from GCCPaolo Bonzini2-1/+12
2006-07-252006-07-25 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini3-3/+39
2006-07-192006-07-19 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-0/+20
2006-06-13Richard Earnshaw <rearnsha@arm.com>Richard Earnshaw2-2/+9
2006-06-07Whitespace fixes.DJ Delorie1-9/+9
2006-05-31Configury changes: update src repository (binutils, gdb, and rda) to useDaniel Jacobowitz2-2/+21
2006-02-142006-02-14 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-6/+18
2006-01-262006-01-16 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-20/+165
2006-01-022006-02-01 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-0/+496
2005-12-202005-12-20 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-6/+6
2005-12-192005-12-19 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini3-0/+18
2005-12-05toplevel:Paolo Bonzini2-0/+35
2005-09-23 * enable.m4: New file.Tom Tromey3-0/+64
2005-08-12toplevel:Paolo Bonzini2-51/+44
2005-07-27 * mt-gnu (CXXFLAGS): Include SYSROOT_CFLAGS_FOR_TARGET.Mark Mitchell1-0/+4
2005-07-27 * config/mt-gnu (CXXFLAGS): Include SYSROOT_CFLAGS_FOR_TARGET.Mark Mitchell1-1/+1
2005-07-162005-07-16 Kelley Cook <kcook@gcc.gnu.org>Kelley Cook3-4/+8
2005-06-14 PR libgcj/19877:Tom Tromey2-1/+7
2005-06-13* depstand.m4, lead-dot.m4: New files.DJ Delorie3-0/+172
2005-05-192005-05-19 Kelley Cook <kcook@gcc.gnu.org>Kelley Cook2-98/+4
2005-05-12PR bootstrap/21230DJ Delorie2-1/+7
2005-04-292005-04-29 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-2/+5
2005-03-30 * config/mh-mingw32: Delete.Joern Rennecke1-7/+0
2005-03-302005-02-28 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-15/+4
2005-03-22top:Zack Weinberg2-3/+8
2005-03-16merge from gccDJ Delorie2-28/+4
2005-02-282005-02-28 Paolo Bonzini <bonzini@gnu.org>Paolo Bonzini2-2/+13
2005-01-23 * warnings.m4 (ACX_PROG_CC_WARNING_ALMOST_PEDANTIC): Don't doJoseph Myers2-4/+11
2004-12-03Introduce config/gxx-include-dir.m4.Richard Sandiford2-0/+30
2004-12-02Introduce and use config/gcc-version.m4.Richard Sandiford2-0/+32
2004-09-25Merge from gcc:DJ Delorie2-0/+101
2004-09-24Merge from gccDJ Delorie1-0/+1
2004-09-242004-09-23 H.J. Lu <hongjiu.lu@intel.com>H.J. Lu2-0/+19
2004-09-23Merge from gcc:DJ Delorie1-0/+2
2004-09-23Merge from gccDJ Delorie19-64/+1981
2004-09-102004-08-31 Robert Bowdidge <bowdidge@apple.com>DJ Delorie2-0/+10
2004-08-132004-08-13 Nathanael Nerode <neroden@gcc.gnu.org>Nathanael Nerode2-0/+30
t">(sizeof(Elf32_Shdr), endian); elf_header.e_shnum = cpu_convert_to_target16(1, endian); } ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s); if (ret < 0) { dump_error(s, "dump: failed to write elf header.\n"); return -1; } return 0; } static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, int phdr_index, target_phys_addr_t offset) { Elf64_Phdr phdr; int ret; int endian = s->dump_info.d_endian; memset(&phdr, 0, sizeof(Elf64_Phdr)); phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian); phdr.p_offset = cpu_convert_to_target64(offset, endian); phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian); if (offset == -1) { /* When the memory is not stored into vmcore, offset will be -1 */ phdr.p_filesz = 0; } else { phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian); } phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian); phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian); ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s); if (ret < 0) { dump_error(s, "dump: failed to write program header table.\n"); return -1; } return 0; } static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, int phdr_index, target_phys_addr_t offset) { Elf32_Phdr phdr; int ret; int endian = s->dump_info.d_endian; memset(&phdr, 0, sizeof(Elf32_Phdr)); phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian); phdr.p_offset = cpu_convert_to_target32(offset, endian); phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian); if (offset == -1) { /* When the memory is not stored into vmcore, offset will be -1 */ phdr.p_filesz = 0; } else { phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian); } phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian); phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian); ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s); if (ret < 0) { dump_error(s, "dump: failed to write program header table.\n"); return -1; } return 0; } static int write_elf64_note(DumpState *s) { Elf64_Phdr phdr; int endian = s->dump_info.d_endian; target_phys_addr_t begin = s->memory_offset - s->note_size; int ret; memset(&phdr, 0, sizeof(Elf64_Phdr)); phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian); phdr.p_offset = cpu_convert_to_target64(begin, endian); phdr.p_paddr = 0; phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian); phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian); phdr.p_vaddr = 0; ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s); if (ret < 0) { dump_error(s, "dump: failed to write program header table.\n"); return -1; } return 0; } static int write_elf64_notes(DumpState *s) { CPUArchState *env; int ret; int id; for (env = first_cpu; env != NULL; env = env->next_cpu) { id = cpu_index(env); ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s); if (ret < 0) { dump_error(s, "dump: failed to write elf notes.\n"); return -1; } } for (env = first_cpu; env != NULL; env = env->next_cpu) { ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s); if (ret < 0) { dump_error(s, "dump: failed to write CPU status.\n"); return -1; } } return 0; } static int write_elf32_note(DumpState *s) { target_phys_addr_t begin = s->memory_offset - s->note_size; Elf32_Phdr phdr; int endian = s->dump_info.d_endian; int ret; memset(&phdr, 0, sizeof(Elf32_Phdr)); phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian); phdr.p_offset = cpu_convert_to_target32(begin, endian); phdr.p_paddr = 0; phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian); phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian); phdr.p_vaddr = 0; ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s); if (ret < 0) { dump_error(s, "dump: failed to write program header table.\n"); return -1; } return 0; } static int write_elf32_notes(DumpState *s) { CPUArchState *env; int ret; int id; for (env = first_cpu; env != NULL; env = env->next_cpu) { id = cpu_index(env); ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s); if (ret < 0) { dump_error(s, "dump: failed to write elf notes.\n"); return -1; } } for (env = first_cpu; env != NULL; env = env->next_cpu) { ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s); if (ret < 0) { dump_error(s, "dump: failed to write CPU status.\n"); return -1; } } return 0; } static int write_elf_section(DumpState *s, int type) { Elf32_Shdr shdr32; Elf64_Shdr shdr64; int endian = s->dump_info.d_endian; int shdr_size; void *shdr; int ret; if (type == 0) { shdr_size = sizeof(Elf32_Shdr); memset(&shdr32, 0, shdr_size); shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian); shdr = &shdr32; } else { shdr_size = sizeof(Elf64_Shdr); memset(&shdr64, 0, shdr_size); shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian); shdr = &shdr64; } ret = fd_write_vmcore(&shdr, shdr_size, s); if (ret < 0) { dump_error(s, "dump: failed to write section header table.\n"); return -1; } return 0; } static int write_data(DumpState *s, void *buf, int length) { int ret; ret = fd_write_vmcore(buf, length, s); if (ret < 0) { dump_error(s, "dump: failed to save memory.\n"); return -1; } return 0; } /* write the memroy to vmcore. 1 page per I/O. */ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start, int64_t size) { int64_t i; int ret; for (i = 0; i < size / TARGET_PAGE_SIZE; i++) { ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); if (ret < 0) { return ret; } } if ((size % TARGET_PAGE_SIZE) != 0) { ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE, size % TARGET_PAGE_SIZE); if (ret < 0) { return ret; } } return 0; } /* get the memory's offset in the vmcore */ static target_phys_addr_t get_offset(target_phys_addr_t phys_addr, DumpState *s) { RAMBlock *block; target_phys_addr_t offset = s->memory_offset; int64_t size_in_block, start; if (s->has_filter) { if (phys_addr < s->begin || phys_addr >= s->begin + s->length) { return -1; } } QLIST_FOREACH(block, &ram_list.blocks, next) { if (s->has_filter) { if (block->offset >= s->begin + s->length || block->offset + block->length <= s->begin) { /* This block is out of the range */ continue; } if (s->begin <= block->offset) { start = block->offset; } else { start = s->begin; } size_in_block = block->length - (start - block->offset); if (s->begin + s->length < block->offset + block->length) { size_in_block -= block->offset + block->length - (s->begin + s->length); } } else { start = block->offset; size_in_block = block->length; } if (phys_addr >= start && phys_addr < start + size_in_block) { return phys_addr - start + offset; } offset += size_in_block; } return -1; } static int write_elf_loads(DumpState *s) { target_phys_addr_t offset; MemoryMapping *memory_mapping; uint32_t phdr_index = 1; int ret; uint32_t max_index; if (s->have_section) { max_index = s->sh_info; } else { max_index = s->phdr_num; } QTAILQ_FOREACH(memory_mapping, &s->list.head, next) { offset = get_offset(memory_mapping->phys_addr, s); if (s->dump_info.d_class == ELFCLASS64) { ret = write_elf64_load(s, memory_mapping, phdr_index++, offset); } else { ret = write_elf32_load(s, memory_mapping, phdr_index++, offset); } if (ret < 0) { return -1; } if (phdr_index >= max_index) { break; } } return 0; } /* write elf header, PT_NOTE and elf note to vmcore. */ static int dump_begin(DumpState *s) { int ret; /* * the vmcore's format is: * -------------- * | elf header | * -------------- * | PT_NOTE | * -------------- * | PT_LOAD | * -------------- * | ...... | * -------------- * | PT_LOAD | * -------------- * | sec_hdr | * -------------- * | elf note | * -------------- * | memory | * -------------- * * we only know where the memory is saved after we write elf note into * vmcore. */ /* write elf header to vmcore */ if (s->dump_info.d_class == ELFCLASS64) { ret = write_elf64_header(s); } else { ret = write_elf32_header(s); } if (ret < 0) { return -1; } if (s->dump_info.d_class == ELFCLASS64) { /* write PT_NOTE to vmcore */ if (write_elf64_note(s) < 0) { return -1; } /* write all PT_LOAD to vmcore */ if (write_elf_loads(s) < 0) { return -1; } /* write section to vmcore */ if (s->have_section) { if (write_elf_section(s, 1) < 0) { return -1; } } /* write notes to vmcore */ if (write_elf64_notes(s) < 0) { return -1; } } else { /* write PT_NOTE to vmcore */ if (write_elf32_note(s) < 0) { return -1; } /* write all PT_LOAD to vmcore */ if (write_elf_loads(s) < 0) { return -1; } /* write section to vmcore */ if (s->have_section) { if (write_elf_section(s, 0) < 0) { return -1; } } /* write notes to vmcore */ if (write_elf32_notes(s) < 0) { return -1; } } return 0; } /* write PT_LOAD to vmcore */ static int dump_completed(DumpState *s) { dump_cleanup(s); return 0; } static int get_next_block(DumpState *s, RAMBlock *block) { while (1) { block = QLIST_NEXT(block, next); if (!block) { /* no more block */ return 1; } s->start = 0; s->block = block; if (s->has_filter) { if (block->offset >= s->begin + s->length || block->offset + block->length <= s->begin) { /* This block is out of the range */ continue; } if (s->begin > block->offset) { s->start = s->begin - block->offset; } } return 0; } } /* write all memory to vmcore */ static int dump_iterate(DumpState *s) { RAMBlock *block; int64_t size; int ret; while (1) { block = s->block; size = block->length; if (s->has_filter) { size -= s->start; if (s->begin + s->length < block->offset + block->length) { size -= block->offset + block->length - (s->begin + s->length); } } ret = write_memory(s, block, s->start, size); if (ret == -1) { return ret; } ret = get_next_block(s, block); if (ret == 1) { dump_completed(s); return 0; } } } static int create_vmcore(DumpState *s) { int ret; ret = dump_begin(s); if (ret < 0) { return -1; } ret = dump_iterate(s); if (ret < 0) { return -1; } return 0; } static ram_addr_t get_start_block(DumpState *s) { RAMBlock *block; if (!s->has_filter) { s->block = QLIST_FIRST(&ram_list.blocks); return 0; } QLIST_FOREACH(block, &ram_list.blocks, next) { if (block->offset >= s->begin + s->length || block->offset + block->length <= s->begin) { /* This block is out of the range */ continue; } s->block = block; if (s->begin > block->offset) { s->start = s->begin - block->offset; } else { s->start = 0; } return s->start; } return -1; } static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, int64_t begin, int64_t length, Error **errp) { CPUArchState *env; int nr_cpus; int ret; if (runstate_is_running()) { vm_stop(RUN_STATE_SAVE_VM); s->resume = true; } else { s->resume = false; } s->errp = errp; s->fd = fd; s->has_filter = has_filter; s->begin = begin; s->length = length; s->start = get_start_block(s); if (s->start == -1) { error_set(errp, QERR_INVALID_PARAMETER, "begin"); goto cleanup; } /* * get dump info: endian, class and architecture. * If the target architecture is not supported, cpu_get_dump_info() will * return -1. * * if we use kvm, we should synchronize the register before we get dump * info. */ nr_cpus = 0; for (env = first_cpu; env != NULL; env = env->next_cpu) { cpu_synchronize_state(env); nr_cpus++; } ret = cpu_get_dump_info(&s->dump_info); if (ret < 0) { error_set(errp, QERR_UNSUPPORTED); goto cleanup; } s->note_size = cpu_get_note_size(s->dump_info.d_class, s->dump_info.d_machine, nr_cpus); if (ret < 0) { error_set(errp, QERR_UNSUPPORTED); goto cleanup; } /* get memory mapping */ memory_mapping_list_init(&s->list); if (paging) { qemu_get_guest_memory_mapping(&s->list); } else { qemu_get_guest_simple_memory_mapping(&s->list); } if (s->has_filter) { memory_mapping_filter(&s->list, s->begin, s->length); } /* * calculate phdr_num * * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow */ s->phdr_num = 1; /* PT_NOTE */ if (s->list.num < UINT16_MAX - 2) { s->phdr_num += s->list.num; s->have_section = false; } else { s->have_section = true; s->phdr_num = PN_XNUM; s->sh_info = 1; /* PT_NOTE */ /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */ if (s->list.num <= UINT32_MAX - 1) { s->sh_info += s->list.num; } else { s->sh_info = UINT32_MAX; } } if (s->dump_info.d_class == ELFCLASS64) { if (s->have_section) { s->memory_offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info + sizeof(Elf64_Shdr) + s->note_size; } else { s->memory_offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->phdr_num + s->note_size; } } else { if (s->have_section) { s->memory_offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info + sizeof(Elf32_Shdr) + s->note_size; } else { s->memory_offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->phdr_num + s->note_size; } } return 0; cleanup: if (s->resume) { vm_start(); } return -1; } void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, int64_t begin, bool has_length, int64_t length, Error **errp) { const char *p; int fd = -1; DumpState *s; int ret; if (has_begin && !has_length) { error_set(errp, QERR_MISSING_PARAMETER, "length"); return; } if (!has_begin && has_length) { error_set(errp, QERR_MISSING_PARAMETER, "begin"); return; } #if !defined(WIN32) if (strstart(file, "fd:", &p)) { fd = monitor_get_fd(cur_mon, p, errp); if (fd == -1) { return; } } #endif if (strstart(file, "file:", &p)) { fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR); if (fd < 0) { error_set(errp, QERR_OPEN_FILE_FAILED, p); return; } } if (fd == -1) { error_set(errp, QERR_INVALID_PARAMETER, "protocol"); return; } s = g_malloc(sizeof(DumpState)); ret = dump_init(s, fd, paging, has_begin, begin, length, errp); if (ret < 0) { g_free(s); return; } if (create_vmcore(s) < 0 && !error_is_set(s->errp)) { error_set(errp, QERR_IO_ERROR); } g_free(s); }