qemu/disas/arm-a64.cc
Paolo Bonzini 875df03b22 osdep: protect qemu/osdep.h with extern "C"
System headers may include templates if compiled with a C++ compiler,
which cause the compiler to complain if qemu/osdep.h is included
within a C++ source file's 'extern "C"' block.  Add
an 'extern "C"' block directly to qemu/osdep.h, so that
system headers can be kept out of it.

There is a stray declaration early in qemu/osdep.h, which needs
to be special cased.  Add a definition in qemu/compiler.h to
make it look nice.

config-host.h, CONFIG_TARGET, exec/poison.h and qemu/compiler.h
are included outside the 'extern "C"' block; that is not
an issue because they consist entirely of preprocessor directives.

This allows us to move the include of osdep.h in our two C++
source files outside the extern "C" block they were previously
using for it, which in turn means that they compile successfully
against newer versions of glib which insist that glib.h is
*not* inside an extern "C" block.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210416135543.20382-3-peter.maydell@linaro.org
[PMM: Moved disas/arm-a64.cc osdep.h include out of its extern "C" block;
 explained in commit message why we're doing this]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2021-04-17 18:44:30 +01:00

104 lines
2.8 KiB
C++

/*
* ARM A64 disassembly output wrapper to libvixl
* Copyright (c) 2013 Linaro Limited
* Written by Claudio Fontana
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
extern "C" {
#include "disas/dis-asm.h"
}
#include "vixl/a64/disasm-a64.h"
using namespace vixl;
static Decoder *vixl_decoder = NULL;
static Disassembler *vixl_disasm = NULL;
/* We don't use libvixl's PrintDisassembler because its output
* is a little unhelpful (trailing newlines, for example).
* Instead we use our own very similar variant so we have
* control over the format.
*/
class QEMUDisassembler : public Disassembler {
public:
QEMUDisassembler() : printf_(NULL), stream_(NULL) { }
~QEMUDisassembler() { }
void SetStream(FILE *stream) {
stream_ = stream;
}
void SetPrintf(fprintf_function printf_fn) {
printf_ = printf_fn;
}
protected:
virtual void ProcessOutput(const Instruction *instr) {
printf_(stream_, "%08" PRIx32 " %s",
instr->InstructionBits(), GetOutput());
}
private:
fprintf_function printf_;
FILE *stream_;
};
static int vixl_is_initialized(void)
{
return vixl_decoder != NULL;
}
static void vixl_init() {
vixl_decoder = new Decoder();
vixl_disasm = new QEMUDisassembler();
vixl_decoder->AppendVisitor(vixl_disasm);
}
#define INSN_SIZE 4
/* Disassemble ARM A64 instruction. This is our only entry
* point from QEMU's C code.
*/
int print_insn_arm_a64(uint64_t addr, disassemble_info *info)
{
uint8_t bytes[INSN_SIZE];
uint32_t instrval;
const Instruction *instr;
int status;
status = info->read_memory_func(addr, bytes, INSN_SIZE, info);
if (status != 0) {
info->memory_error_func(status, addr, info);
return -1;
}
if (!vixl_is_initialized()) {
vixl_init();
}
((QEMUDisassembler *)vixl_disasm)->SetPrintf(info->fprintf_func);
((QEMUDisassembler *)vixl_disasm)->SetStream(info->stream);
instrval = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24;
instr = reinterpret_cast<const Instruction *>(&instrval);
vixl_disasm->MapCodeAddress(addr, instr);
vixl_decoder->Decode(instr);
return INSN_SIZE;
}