From 6219b84915cb80caf2c4e69f654b67f2cfc0530d Mon Sep 17 00:00:00 2001 From: TheFloW Date: Wed, 4 Jan 2017 20:08:04 +0100 Subject: [PATCH] Added coredump viewer --- CMakeLists.txt | 3 +- archiveRAR.c | 2 +- coredump.c | 337 +++++++++++++++++++++++++++++++++++++++ coredump.h | 24 +++ elf.c | 2 - file.c | 6 +- file.h | 4 +- main.c | 42 +++-- main.h | 7 + unrarlib/unrarlibutils.c | 8 + 10 files changed, 410 insertions(+), 25 deletions(-) create mode 100644 coredump.c create mode 100644 coredump.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ee2dec13..9f80a5e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(VITA_TITLEID "VITASHELL") set(VITA_VERSION "01.43") # Flags and includes -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -Wno-unused-variable -Wno-unused-but-set-variable ") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -Wno-unused-variable -Wno-unused-but-set-variable -fno-lto") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions") set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1") set(VITA_MAKE_FSELF_FLAGS "${VITA_MAKE_FSELF_FLAGS} -a 0x2800000000000001") @@ -67,6 +67,7 @@ add_executable(VitaShell text.c hex.c sfo.c + coredump.c settings.c property_dialog.c uncommon_dialog.c diff --git a/archiveRAR.c b/archiveRAR.c index 5eeac26d..4d7057c3 100644 --- a/archiveRAR.c +++ b/archiveRAR.c @@ -198,7 +198,7 @@ int extractRARArchivePath(char *src, char *dst, FileProcessParam *param) { SceUID fddst = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); -struct ExtractHeader header = {file:fddst,offset:0,memPtr:NULL,bufferSize:0,param:param}; + struct ExtractHeader header = {file:fddst,offset:0,memPtr:NULL,bufferSize:0,param:param}; int result = extractRAR(filepath,src + (filePathLength + sizeof(char)),&header); sceIoClose(fddst); diff --git a/coredump.c b/coredump.c new file mode 100644 index 00000000..c9776f9d --- /dev/null +++ b/coredump.c @@ -0,0 +1,337 @@ +/* + VitaShell + Copyright (C) 2015-2016, TheFloW + + 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 3 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 . +*/ + +#include "main.h" +#include "file.h" +#include "utils.h" +#include "theme.h" +#include "coredump.h" +#include "elf.h" + +typedef struct { + int unk_0; // 0x00 + int size; // 0x04 + int unk_8; // 0x08 + char name[16]; // 0x0C + int unk_1C; // 0x1C + int num; // 0x20 +} InfoHeader; // 0x24 + +typedef struct { + int unk; // 0x00 + int perm; // 0x04 + uint32_t addr; // 0x08 + uint32_t size; // 0x0C + int unk_10; // 0x10 +} ModuleSegment; // 0x14 + +typedef struct { + int unk_0; // 0x00 + int uid; // 0x04 + int sdk_version; // 0x08 + int version; // 0xC + int unk_10; // 0x10 + int addr_14; // 0x14 + int unk_18; // 0x18 + int addr_1C; // 0x1C + int unk_20; // 0x20 + char name[28]; // 0x24 + int unk_44; // 0x40 + int unk_48; // 0x44 2 + uint32_t nid; // 0x48 + int num_segments; // 0x4C + ModuleSegment segments[1]; // 0x50 + uint32_t addr[4]; // 0x78 +} ModuleInfoOneSegment; // 0x88 + +typedef struct { + int unk_0; // 0x00 + int uid; // 0x04 + int sdk_version; // 0x08 + int version; // 0xC + int unk_10; // 0x10 + int addr_14; // 0x14 + int unk_18; // 0x18 + int addr_1C; // 0x1C + int unk_20; // 0x20 + char name[28]; // 0x24 + int unk_44; // 0x40 + int unk_48; // 0x44 2 + uint32_t nid; // 0x48 + int num_segments; // 0x4C + ModuleSegment segments[2]; // 0x50 + uint32_t addr[4]; // 0x78 +} ModuleInfoTwoSegment; // 0x88 + +typedef struct { + int unk; // 0x00 + int uid; // 0x04 + char name[32]; // 0x08 + int type; // 0x28 + uint32_t vaddr; // 0x2C + uint32_t vsize; // 0x30 + int unk_34; + int unk_38; + int unk_3C; + int unk_40; + int unk_44; +} MemBlkInfo; // 0x48 + +typedef struct { + int size; // 0x00 + int uid; // 0x04 + char name[32]; // 0x08 + int unk_28; // 0x28 + int unk_2C[18]; // 0x2C + int cause; // 0x74 + int unk_78[9]; // 0x78 + uint32_t pc; // 0x9C + int unk_A0[10]; // 0xA0 +} ThreadInfo; // 0xC8 + +typedef struct { + int size; // 0x00 + int uid; // 0x04 + uint32_t regs[16]; // 0x08 + int unk[75]; // 0x48 + uint32_t bad_v_addr; // 0x174 +} ThreadRegInfo; // 0x178 + +// ARM registers +static char *regnames[] = { "a1", "a2", "a3", "a4", + "v1", "v2", "v3", "v4", + "v5", "v6", "v7", "v8", + "ip", "sp", "lr", "pc" }; + +char *getCauseName(int cause) { + switch (cause) { + case 0x30002: + return "Undefined instruction exception"; + + case 0x30003: + return "Prefetch abort exception"; + + case 0x30004: + return "Data abort exception"; + + case 0x60080: + return "Division by zero"; + } + + return "Unknown cause"; +} + +int decompressGzip(uint8_t *dst, int size_dst, uint8_t *src, int size_src) { + z_stream z; + memset(&z, 0, sizeof(z_stream)); + + z.avail_in = size_src; + z.next_in = src; + z.avail_out = size_dst; + z.next_out = dst; + + if (inflateInit2(&z, 15 + 32) != Z_OK) + return -1; + + if (inflate(&z, Z_FINISH) != Z_STREAM_END) { + inflateEnd(&z); + return -2; + } + + inflateEnd(&z); + return z.total_out; +} + +int coredumpViewer(char *file) { + void *buffer = malloc(BIG_BUFFER_SIZE); + if (!buffer) + return -1; + + int size = ReadFile(file, buffer, BIG_BUFFER_SIZE); + + if (*(uint16_t *)buffer == 0x8B1F) { + void *out_buf = malloc(BIG_BUFFER_SIZE); + if (!out_buf) { + free(buffer); + return -2; + } + + int out_size = decompressGzip(out_buf, BIG_BUFFER_SIZE, buffer, size); + if (out_size < 0) { + free(out_buf); + free(buffer); + return -3; + } + + memcpy(buffer, out_buf, out_size); + + free(out_buf); + } + + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buffer; + Elf32_Phdr *phdr = (Elf32_Phdr *)((uint32_t)buffer + ehdr->e_phoff); + + if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || + ehdr->e_ident[EI_MAG1] != ELFMAG1 || + ehdr->e_ident[EI_MAG2] != ELFMAG2 || + ehdr->e_ident[EI_MAG3] != ELFMAG3) { + free(buffer); + return -4; + } + + char thname[32], modname[32]; + SceUID thid = -1, modid = -1; + uint32_t epc = -1, rel_epc = -1; + int cause = -1; + uint32_t bad_v_addr = -1; + uint32_t regs[16]; + + int i; + for (i = 0; i < ehdr->e_phnum; i++) { + if (phdr[i].p_type == 0x4) { + void *program = malloc(phdr[i].p_filesz); + if (!program) { + free(buffer); + return -5; + } + + memcpy(program, buffer + phdr[i].p_offset, phdr[i].p_filesz); + + InfoHeader *info = (InfoHeader *)program; + + if (strcmp(info->name, "THREAD_INFO") == 0) { + int j; + for (j = 0; j < ((InfoHeader *)program)->num; j++) { + ThreadInfo *thread_info = (ThreadInfo *)(program + sizeof(InfoHeader)); + if (thread_info[j].cause != 0) { + strcpy(thname, thread_info[j].name); + thid = thread_info[j].uid; + epc = thread_info[j].pc; + cause = thread_info[j].cause; + break; + } + } + } else if (strcmp(info->name, "THREAD_REG_INFO") == 0) { + int j; + for (j = 0; j < ((InfoHeader *)program)->num; j++) { + ThreadRegInfo *thread_reg_info = (ThreadRegInfo *)(program + sizeof(InfoHeader)); + + if (thread_reg_info[j].uid == thid) { + memcpy(®s, thread_reg_info[j].regs, sizeof(regs)); + bad_v_addr = thread_reg_info[j].bad_v_addr; + break; + } + } + } else if (strcmp(info->name, "MODULE_INFO") == 0) { + uint32_t offset = 0; + + int j; + for (j = 0; j < ((InfoHeader *)program)->num; j++) { + ModuleInfoTwoSegment *mod_info = (ModuleInfoTwoSegment *)(program + sizeof(InfoHeader) + offset); + + if (epc >= mod_info->segments[0].addr && epc < (mod_info->segments[0].addr + mod_info->segments[0].size)) { + strcpy(modname, mod_info->name); + modid = mod_info->uid; + rel_epc = epc - mod_info->segments[0].addr; + break; + } + + if (mod_info->num_segments == 2) { + offset += sizeof(ModuleInfoTwoSegment); + } else { + offset += sizeof(ModuleInfoOneSegment); + } + } + } + + free(program); + } + } + + while (1) { + readPad(); + + if (pressed_buttons & SCE_CTRL_CANCEL) { + break; + } + + // Start drawing + startDrawing(bg_text_image); + + // Draw shell info + drawShellInfo(file); + + float y = START_Y; + + // Exception + pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, FONT_SIZE, "Exception"); + pgf_draw_text(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, getCauseName(cause)); + y += FONT_Y_SPACE; + + // Thread ID + pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, FONT_SIZE, "Thread ID"); + pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, "0x%08X", thid); + y += FONT_Y_SPACE; + + // Thread name + pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, FONT_SIZE, "Thread name"); + pgf_draw_text(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, thname); + y += FONT_Y_SPACE; + + // EPC + pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, FONT_SIZE, "EPC"); + if (rel_epc != -1) + pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, "%s + 0x%08X", modname, rel_epc); + else + pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, "0x%08X", epc); + y += FONT_Y_SPACE; + + // Cause + pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, FONT_SIZE, "Cause"); + pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, "0x%08X", cause); + y += FONT_Y_SPACE; + + // BadVAddr + pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, FONT_SIZE, "BadVAddr"); + pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, FONT_SIZE, "0x%08X", bad_v_addr); + y += FONT_Y_SPACE; + + // Registers + int j; + for (j = 0; j < 4; j++) { + float x = SHELL_MARGIN_X; + + int i; + for (i = 0; i < 4; i++) { + pgf_draw_textf(x, y, TEXT_COLOR, FONT_SIZE, "%s:", regnames[j * 4 + i]); + x += COREDUMP_REGISTER_NAME_SPACE; + + pgf_draw_textf(x, y, TEXT_COLOR, FONT_SIZE, "0x%08X", regs[j * 4 + i]); + x += COREDUMP_REGISTER_SPACE; + } + + y += FONT_Y_SPACE; + } + + // End drawing + endDrawing(); + } + + free(buffer); + return 0; +} \ No newline at end of file diff --git a/coredump.h b/coredump.h new file mode 100644 index 00000000..2b4e3e39 --- /dev/null +++ b/coredump.h @@ -0,0 +1,24 @@ +/* + VitaShell + Copyright (C) 2015-2016, TheFloW + + 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 3 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 . +*/ + +#ifndef __COREDUMP_H__ +#define __COREDUMP_H__ + +int coredumpViewer(char *file); + +#endif \ No newline at end of file diff --git a/elf.c b/elf.c index 5890ae93..916fa3f2 100644 --- a/elf.c +++ b/elf.c @@ -19,8 +19,6 @@ #include "main.h" #include "elf.h" -#include - //! Module Information typedef struct { uint16_t attr; //!< Attribute diff --git a/file.c b/file.c index 71e42e92..3cc152f5 100644 --- a/file.c +++ b/file.c @@ -23,13 +23,11 @@ #include "sha1.h" static char *devices[] = { - // "app0:", "gro0:", "grw0:", "os0:", "pd0:", "sa0:", - // "savedata0:", "tm0:", "ud0:", "ur0:", @@ -599,6 +597,8 @@ typedef struct { } ExtensionType; static ExtensionType extension_types[] = { + { ".PSP2DMP", FILE_TYPE_PSP2DMP }, + { ".TMP", FILE_TYPE_PSP2DMP }, { ".BMP", FILE_TYPE_BMP }, { ".INI", FILE_TYPE_INI }, { ".JPG", FILE_TYPE_JPEG }, @@ -606,12 +606,12 @@ static ExtensionType extension_types[] = { { ".MP3", FILE_TYPE_MP3 }, { ".OGG", FILE_TYPE_OGG }, { ".PNG", FILE_TYPE_PNG }, + { ".RAR", FILE_TYPE_RAR }, { ".SFO", FILE_TYPE_SFO }, { ".TXT", FILE_TYPE_TXT }, { ".VPK", FILE_TYPE_VPK }, { ".XML", FILE_TYPE_XML }, { ".ZIP", FILE_TYPE_ZIP }, - { ".RAR", FILE_TYPE_RAR }, }; int getFileType(char *file) { diff --git a/file.h b/file.h index 3ff371cc..833452fb 100644 --- a/file.h +++ b/file.h @@ -25,6 +25,7 @@ #define MAX_PATH_LENGTH 1024 #define MAX_NAME_LENGTH 256 #define MAX_SHORT_NAME_LENGTH 64 +#define MAX_DIR_LEVELS 16 #define DIRECTORY_SIZE (4 * 1024) #define TRANSFER_SIZE (64 * 1024) @@ -34,18 +35,19 @@ enum FileTypes { FILE_TYPE_UNKNOWN, + FILE_TYPE_PSP2DMP, FILE_TYPE_BMP, FILE_TYPE_INI, FILE_TYPE_JPEG, FILE_TYPE_MP3, FILE_TYPE_OGG, FILE_TYPE_PNG, + FILE_TYPE_RAR, FILE_TYPE_SFO, FILE_TYPE_TXT, FILE_TYPE_VPK, FILE_TYPE_XML, FILE_TYPE_ZIP, - FILE_TYPE_RAR, }; enum FileSortFlags { diff --git a/main.c b/main.c index b0d3af56..63f0ef65 100644 --- a/main.c +++ b/main.c @@ -37,14 +37,13 @@ #include "language.h" #include "utils.h" #include "sfo.h" +#include "coredump.h" #include "list_dialog.h" #include "archiveRAR.h" #include "audio/vita_audio.h" -int _newlib_heap_size_user = 128 * 1024 * 1024; - -#define MAX_DIR_LEVELS 1024 +int _newlib_heap_size_user = 64 * 1024 * 1024; // Context menu static float ctx_menu_max_width = 0.0f, ctx_menu_more_max_width = 0.0f; @@ -117,12 +116,14 @@ int isInArchive() { void dirUpCloseArchive() { if (isInArchive() && dir_level_archive >= dir_level) { is_in_archive = 0; - enum FileTypes archiveType = getArchiveType(); - if(archiveType == FILE_TYPE_RAR) - archiveRARClose(); - else if(archiveType == FILE_TYPE_ZIP) - archiveClose(); - dir_level_archive = -1; + + enum FileTypes archiveType = getArchiveType(); + if(archiveType == FILE_TYPE_RAR) + archiveRARClose(); + else if(archiveType == FILE_TYPE_ZIP) + archiveClose(); + + dir_level_archive = -1; } } @@ -281,11 +282,12 @@ int handleFile(char *file, FileListEntry *entry) { int type = getFileType(file); switch (type) { + case FILE_TYPE_PSP2DMP: case FILE_TYPE_MP3: case FILE_TYPE_OGG: + case FILE_TYPE_RAR: case FILE_TYPE_VPK: case FILE_TYPE_ZIP: - case FILE_TYPE_RAR: if (isInArchive()) type = FILE_TYPE_UNKNOWN; @@ -293,6 +295,10 @@ int handleFile(char *file, FileListEntry *entry) { } switch (type) { + case FILE_TYPE_PSP2DMP: + res = coredumpViewer(file); + break; + case FILE_TYPE_INI: case FILE_TYPE_TXT: case FILE_TYPE_XML: @@ -310,7 +316,15 @@ int handleFile(char *file, FileListEntry *entry) { case FILE_TYPE_OGG: res = audioPlayer(file, type, &file_list, entry, &base_pos, &rel_pos); break; - + + case FILE_TYPE_RAR: + res = archiveRAROpen(file); + break; + + case FILE_TYPE_SFO: + res = SFOReader(file); + break; + case FILE_TYPE_VPK: initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[INSTALL_QUESTION]); dialog_step = DIALOG_STEP_INSTALL_QUESTION; @@ -319,12 +333,6 @@ int handleFile(char *file, FileListEntry *entry) { case FILE_TYPE_ZIP: res = archiveOpen(file); break; - case FILE_TYPE_RAR: - res = archiveRAROpen(file); - break; - case FILE_TYPE_SFO: - res = SFOReader(file); - break; default: errorDialog(type); diff --git a/main.h b/main.h index 0e2ca4f9..d4938b73 100644 --- a/main.h +++ b/main.h @@ -59,6 +59,8 @@ #include #include +#include + #include #include @@ -119,6 +121,11 @@ #define HEX_CHAR_X (SCREEN_WIDTH - SHELL_MARGIN_X - 0x10 * FONT_X_SPACE) #define HEX_OFFSET_SPACE 34.0f +// Coredump +#define COREDUMP_INFO_X (SHELL_MARGIN_X + 160.0f) +#define COREDUMP_REGISTER_NAME_SPACE 45.0f +#define COREDUMP_REGISTER_SPACE 165.0f + // Scroll bar #define SCROLL_BAR_X 0.0f #define SCROLL_BAR_WIDTH 8.0f diff --git a/unrarlib/unrarlibutils.c b/unrarlib/unrarlibutils.c index e41b6442..70188348 100644 --- a/unrarlib/unrarlibutils.c +++ b/unrarlib/unrarlibutils.c @@ -1,5 +1,13 @@ #include "unrarlibutils.h" +int getcwd() { + return 0; +} + +int fsync() { + return 0; +} + static void* rar_open(const char *filename, unsigned int om) { struct RAROpenArchiveData arc_open; arc_open.ArcName = (char*)filename;