Permalink
Browse files

Merge branch 'master' into medusa

  • Loading branch information...
endrift committed Jul 16, 2017
2 parents fe797de + 0f5dab6 commit 45169bc0f27dc68aa27bc33da809a13f8753ed4e
View
@@ -8,14 +8,16 @@ Misc:
- DS GX: Clean up and unify texture mapping
0.7.0: (Future)
+Features:
+ - ELF support
Bugfixes:
- GB Audio: Make audio unsigned with bias (fixes mgba.io/i/749)
Misc:
- GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
- All: Make FIXED_ROM_BUFFER an option instead of 3DS-only
-0.6.0: (Future)
+0.6.0: (2017-07-16)
Features:
- Library view
- Sprite viewer
@@ -190,6 +192,8 @@ Bugfixes:
- Core: Fix rewinding getting out of sync (fixes mgba.io/i/791)
- Qt: Fix GL-less build
- Qt: Fix Software renderer not handling alpha bits properly
+ - Qt: Fix screen background improperly stretching
+ - SDL: Fix cheats not loading
Misc:
- GB Serialize: Add MBC state serialization
- GBA Memory: Call crash callbacks regardless of if hard crash is enabled
View
@@ -16,6 +16,7 @@ set(USE_PNG ON CACHE BOOL "Whether or not to enable PNG support")
set(USE_LIBZIP ON CACHE BOOL "Whether or not to enable LIBZIP support")
set(USE_MAGICK ON CACHE BOOL "Whether or not to enable ImageMagick support")
set(USE_SQLITE3 ON CACHE BOOL "Whether or not to enable SQLite3 support")
+set(USE_ELF ON CACHE BOOL "Whether or not to enable ELF support")
set(M_CORE_GBA ON CACHE BOOL "Build Game Boy Advance core")
set(M_CORE_GB ON CACHE BOOL "Build Game Boy core")
set(M_CORE_DS ON CACHE BOOL "Build DS core")
@@ -402,6 +403,7 @@ find_feature(USE_MAGICK "MagickWand")
find_feature(USE_EPOXY "epoxy")
find_feature(USE_CMOCKA "cmocka")
find_feature(USE_SQLITE3 "sqlite3")
+find_feature(USE_ELF "libelf")
find_feature(ENABLE_PYTHON "PythonLibs")
# Features
@@ -620,6 +622,17 @@ if(USE_SQLITE3)
list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/sqlite3/no-intro.c")
endif()
+if(USE_ELF)
+ list(APPEND FEATURES ELF)
+ include_directories(AFTER ${LIBELF_INCLUDE_DIRS})
+ find_file(ELF_REPL_H elf_repl.h PATHS ${LIBELF_INCLUDE_DIRS})
+ if (ELF_REPL_H)
+ add_definitions(-DUSE_ELF_REPL)
+ endif()
+ list(APPEND DEPENDENCY_LIB ${LIBELF_LIBRARIES})
+ set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libelfg0")
+endif()
+
if(ENABLE_SCRIPTING)
list(APPEND ENABLES SCRIPTING)
@@ -967,6 +980,7 @@ if(NOT QUIET)
message(STATUS " ZIP support: ${SUMMARY_ZIP}")
message(STATUS " 7-Zip support: ${USE_LZMA}")
message(STATUS " SQLite3 game database: ${USE_SQLITE3}")
+ message(STATUS " ELF loading support: ${USE_ELF}")
message(STATUS " OpenGL support: ${SUMMARY_GL}")
message(STATUS "Frontends:")
message(STATUS " Qt: ${BUILD_QT}")
View
@@ -160,6 +160,7 @@ medusa has no hard dependencies, however, the following optional dependencies ar
- libzip or zlib: for loading ROMs stored in zip files.
- ImageMagick: for GIF recording.
- SQLite3: for game databases.
+- libelf: for ELF loading.
SQLite3, libpng, and zlib are included with the emulator, so they do not need to be externally compiled first.
@@ -0,0 +1,51 @@
+/* Copyright (c) 2013-2017 Jeffrey Pfau
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef ELF_READ_H
+#define ELF_READ_H
+
+#include <mgba-util/common.h>
+
+CXX_GUARD_START
+
+#ifdef USE_ELF
+
+#include <libelf.h>
+
+#if USE_ELF_REPL
+#include <elf_repl.h>
+#else
+#include <elf.h>
+#endif
+
+#include <mgba-util/vector.h>
+
+struct ELF;
+struct VFile;
+
+DECLARE_VECTOR(ELFProgramHeaders, Elf32_Phdr);
+DECLARE_VECTOR(ELFSectionHeaders, Elf32_Shdr);
+
+struct ELF* ELFOpen(struct VFile*);
+void ELFClose(struct ELF*);
+
+void* ELFBytes(struct ELF*, size_t* size);
+
+uint16_t ELFMachine(struct ELF*);
+uint32_t ELFEntry(struct ELF*);
+
+void ELFGetProgramHeaders(struct ELF*, struct ELFProgramHeaders*);
+
+size_t ELFFindSection(struct ELF*, const char* name);
+void ELFGetSectionHeaders(struct ELF*, struct ELFSectionHeaders*);
+Elf32_Shdr* ELFGetSectionHeader(struct ELF*, size_t index);
+
+const char* ELFGetString(struct ELF*, size_t section, size_t string);
+
+#endif
+
+CXX_GUARD_END
+
+#endif
View
@@ -196,6 +196,14 @@ void mCoreLoadForeignConfig(struct mCore* core, const struct mCoreConfig* config
void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc);
+void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size);
+
+#ifdef USE_ELF
+struct ELF;
+bool mCoreLoadELF(struct mCore* core, struct ELF* elf);
+void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF*);
+#endif
+
CXX_GUARD_END
#endif
@@ -24,6 +24,7 @@ struct mScriptEngine {
bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf);
void (*run)(struct mScriptEngine*);
+ bool (*lookupSymbol)(struct mScriptEngine*, const char* name, int32_t* out);
#ifdef USE_DEBUGGERS
void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
@@ -44,6 +45,8 @@ void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReas
void mScriptBridgeRun(struct mScriptBridge*);
bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
+bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out);
+
CXX_GUARD_END
#endif
@@ -91,6 +91,7 @@ struct mDebugger {
struct mCPUComponent d;
struct mDebuggerPlatform* platform;
enum mDebuggerState state;
+ enum mDebuggerType type;
struct mCore* core;
struct mScriptBridge* bridge;
@@ -168,6 +168,7 @@ void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
bool GBALoadMB(struct GBA* gba, struct VFile* vf);
+bool GBALoadNull(struct GBA* gba);
bool GBAIsROM(struct VFile* vf);
bool GBAIsMB(struct VFile* vf);
View
@@ -8,6 +8,11 @@
#include <mgba/core/log.h>
#include <mgba/core/serialize.h>
#include <mgba-util/vfs.h>
+#include <mgba/internal/debugger/symbols.h>
+
+#ifdef USE_ELF
+#include <mgba-util/elf-read.h>
+#endif
#ifdef M_CORE_GB
#include <mgba/gb/core.h>
@@ -280,3 +285,67 @@ void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
core->rtc.custom = rtc;
core->rtc.override = RTC_CUSTOM_START;
}
+
+void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size) {
+ const struct mCoreMemoryBlock* blocks;
+ size_t nBlocks = core->listMemoryBlocks(core, &blocks);
+ size_t i;
+ for (i = 0; i < nBlocks; ++i) {
+ if (!(blocks[i].flags & mCORE_MEMORY_MAPPED)) {
+ continue;
+ }
+ if (start < blocks[i].start) {
+ continue;
+ }
+ if (start >= blocks[i].start + blocks[i].size) {
+ continue;
+ }
+ uint8_t* out = core->getMemoryBlock(core, blocks[i].id, size);
+ out += start - blocks[i].start;
+ *size -= start - blocks[i].start;
+ return out;
+ }
+ return NULL;
+}
+
+#ifdef USE_ELF
+bool mCoreLoadELF(struct mCore* core, struct ELF* elf) {
+ struct ELFProgramHeaders ph;
+ ELFProgramHeadersInit(&ph, 0);
+ ELFGetProgramHeaders(elf, &ph);
+ size_t i;
+ for (i = 0; i < ELFProgramHeadersSize(&ph); ++i) {
+ size_t bsize, esize;
+ Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i);
+ void* block = mCoreGetMemoryBlock(core, phdr->p_paddr, &bsize);
+ char* bytes = ELFBytes(elf, &esize);
+ if (block && bsize >= phdr->p_filesz && esize >= phdr->p_filesz + phdr->p_offset) {
+ memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF* elf) {
+ size_t symIndex = ELFFindSection(elf, ".symtab");
+ size_t names = ELFFindSection(elf, ".strtab");
+ Elf32_Shdr* symHeader = ELFGetSectionHeader(elf, symIndex);
+ char* bytes = ELFBytes(elf, NULL);
+
+ Elf32_Sym* syms = (Elf32_Sym*) &bytes[symHeader->sh_offset];
+ size_t i;
+ for (i = 0; i * sizeof(*syms) < symHeader->sh_size; ++i) {
+ if (!syms[i].st_name || ELF32_ST_TYPE(syms[i].st_info) == STT_FILE) {
+ continue;
+ }
+ const char* name = ELFGetString(elf, names, syms[i].st_name);
+ if (name[0] == '$') {
+ continue;
+ }
+ mDebuggerSymbolAdd(symbols, name, syms[i].st_value, -1);
+ }
+}
+
+#endif
View
@@ -19,6 +19,12 @@ struct mScriptInfo {
bool success;
};
+struct mScriptSymbol {
+ const char* name;
+ int32_t* out;
+ bool success;
+};
+
static void _seDeinit(void* value) {
struct mScriptEngine* se = value;
se->deinit(se);
@@ -33,6 +39,15 @@ static void _seTryLoad(const char* key, void* value, void* user) {
}
}
+static void _seLookupSymbol(const char* key, void* value, void* user) {
+ UNUSED(key);
+ struct mScriptEngine* se = value;
+ struct mScriptSymbol* si = user;
+ if (!si->success) {
+ si->success = se->lookupSymbol(se, si->name, si->out);
+ }
+}
+
static void _seRun(const char* key, void* value, void* user) {
UNUSED(key);
UNUSED(user);
@@ -111,3 +126,13 @@ bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
vf->close(vf);
return info.success;
}
+
+bool mScriptBridgeLookupSymbol(struct mScriptBridge* sb, const char* name, int32_t* out) {
+ struct mScriptSymbol info = {
+ .name = name,
+ .out = out,
+ .success = false
+ };
+ HashTableEnumerate(&sb->engines, _seLookupSymbol, &info);
+ return info.success;
+}
@@ -551,6 +551,11 @@ static void _lookupIdentifier(struct mDebugger* debugger, const char* name, stru
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
if (cliDebugger->system) {
uint32_t value;
+#ifdef ENABLE_SCRIPTING
+ if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, &dv->intValue)) {
+ return;
+ }
+#endif
if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) {
return;
}
@@ -832,6 +837,7 @@ void CLIDebuggerCreate(struct CLIDebugger* debugger) {
debugger->d.custom = _cliDebuggerCustom;
debugger->d.paused = _commandLine;
debugger->d.entered = _reportEntry;
+ debugger->d.type = DEBUGGER_CLI;
debugger->system = NULL;
debugger->backend = NULL;
View
@@ -658,6 +658,7 @@ void GDBStubCreate(struct GDBStub* stub) {
stub->d.paused = _gdbStubWait;
stub->d.entered = _gdbStubEntered;
stub->d.custom = _gdbStubPoll;
+ stub->d.type = DEBUGGER_GDB;
stub->untilPoll = GDB_STUB_INTERVAL;
stub->lineAck = GDB_ACK_PENDING;
stub->shouldBlock = false;
View
@@ -8,6 +8,7 @@
#include <mgba/core/core.h>
#include <mgba/core/log.h>
#include <mgba/internal/arm/debugger/debugger.h>
+#include <mgba/internal/debugger/symbols.h>
#include <mgba/internal/gba/cheats.h>
#include <mgba/internal/gba/gba.h>
#include <mgba/internal/gba/io.h>
@@ -20,6 +21,9 @@
#include <mgba/internal/gba/renderers/video-software.h>
#include <mgba/internal/gba/savedata.h>
#include <mgba/internal/gba/serialize.h>
+#ifdef USE_ELF
+#include <mgba-util/elf-read.h>
+#endif
#include <mgba-util/memory.h>
#include <mgba-util/patch.h>
#include <mgba-util/vfs.h>
@@ -318,6 +322,15 @@ static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
}
static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) {
+#ifdef USE_ELF
+ struct ELF* elf = ELFOpen(vf);
+ if (elf) {
+ GBALoadNull(core->board);
+ bool success = mCoreLoadELF(core, elf);
+ ELFClose(elf);
+ return success;
+ }
+#endif
if (GBAIsMB(vf)) {
return GBALoadMB(core->board, vf);
}
@@ -718,7 +731,27 @@ static void _GBACoreDetachDebugger(struct mCore* core) {
}
static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) {
- // TODO
+#ifdef USE_ELF
+ bool closeAfter = false;
+ core->symbolTable = mDebuggerSymbolTableCreate();
+#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
+ if (!vf) {
+ closeAfter = true;
+ vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".elf", O_RDONLY);
+ }
+#endif
+ if (!vf) {
+ return;
+ }
+ struct ELF* elf = ELFOpen(vf);
+ if (elf) {
+ mCoreLoadELFSymbols(core->symbolTable, elf);
+ ELFClose(elf);
+ }
+ if (closeAfter) {
+ vf->close(vf);
+ }
+#endif
}
#endif
Oops, something went wrong.

0 comments on commit 45169bc

Please sign in to comment.