Embedded TCC code no longer brings down the entire IDE on a sigsegv!
This commit is contained in:
parent
4b32b111cf
commit
917eedb95b
9 changed files with 155 additions and 24 deletions
|
@ -76,6 +76,7 @@ add_custom_target(GENERATE_UI_HEADERS
|
|||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libz.a
|
||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
|
||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.a
|
||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libsigsegv.a
|
||||
)
|
||||
add_dependencies(${CMAKE_PROJECT_NAME} GENERATE_UI_HEADERS)
|
||||
|
||||
|
@ -122,6 +123,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
|
|||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libz.a
|
||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
|
||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.a
|
||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libsigsegv.a
|
||||
${GTK3_LIBRARIES}
|
||||
-ldl
|
||||
-pthread
|
||||
|
|
|
@ -24,13 +24,32 @@
|
|||
|
||||
|
||||
#include <tcclib.h>
|
||||
#include <float.h>
|
||||
#include <stdalign.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdnoreturn.h>
|
||||
|
||||
|
||||
// These are valid for 64 bit hosts.
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
|
||||
// Our shared data.
|
||||
extern char **___recipeTargets;
|
||||
|
||||
|
||||
extern void recipeAddTarget(char *target);
|
||||
extern void recipeMessage(char *format, ...);
|
||||
// Things missing that are nice to have.
|
||||
extern int fputc(int c, FILE *stream);
|
||||
extern void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
||||
|
||||
// Our API.
|
||||
extern char *utilCreateString(char *format, ...);
|
||||
extern void recipeAddTarget(char *target);
|
||||
extern void recipeMessage(char *format, ...);
|
||||
|
||||
|
||||
#endif // RECIPE_H
|
||||
|
|
|
@ -23,12 +23,34 @@
|
|||
#include "common.h"
|
||||
#include "compiler.h"
|
||||
#include "libtcc.h"
|
||||
#include "sigsegv.h"
|
||||
#include "project.h"
|
||||
#include "messages.h"
|
||||
#include "utils.h"
|
||||
#include "array.h"
|
||||
|
||||
|
||||
#if HAVE_SIGSEGV_RECOVERY
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
// Windows doesn't have sigset_t.
|
||||
typedef int sigset_t;
|
||||
#define sigemptyset(set)
|
||||
#define sigprocmask(how,set,oldset)
|
||||
#endif
|
||||
|
||||
volatile int runPass = 0;
|
||||
jmp_buf runRecipe;
|
||||
sigset_t runSigSet;
|
||||
|
||||
static void sigHandlerContinuation(void *arg1, void *arg2, void *arg3);
|
||||
int sigHandler(void *faultAddress, int serious);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
char **___recipeTargets = NULL;
|
||||
|
||||
|
||||
|
@ -49,7 +71,10 @@ static void compilerErrorHandler(void *opaque, const char *msg) {
|
|||
// All the paths passed in here are expected to be complete and absolute.
|
||||
int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context) {
|
||||
TCCState *s;
|
||||
int result;
|
||||
char *oldLocation;
|
||||
char c;
|
||||
int x;
|
||||
int result = -255;
|
||||
int (*entry)(char *, char *);
|
||||
|
||||
___recipeTargets = NULL;
|
||||
|
@ -60,9 +85,15 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
|||
return -1;
|
||||
}
|
||||
|
||||
tcc_set_options(s, "-Wall -Wno-write-strings");
|
||||
// __resourcePath comes in with a trailing slash. Temporarily remove it.
|
||||
x = strlen(__resourcePath) - 1;
|
||||
c = __resourcePath[x];
|
||||
__resourcePath[x] = 0;
|
||||
tcc_set_lib_path(s, __resourcePath);
|
||||
tcc_add_sysinclude_path(s, __resourcePath);
|
||||
__resourcePath[x] = c;
|
||||
|
||||
tcc_set_options(s, "-Wall -Wno-write-strings");
|
||||
tcc_set_error_func(s, stdout, compilerErrorHandler);
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
|
||||
|
@ -72,9 +103,13 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
|||
return -4;
|
||||
}
|
||||
|
||||
tcc_add_symbol(s, "fputc", fputc);
|
||||
tcc_add_symbol(s, "qsort", qsort);
|
||||
|
||||
tcc_add_symbol(s, "___recipeTargets", ___recipeTargets);
|
||||
tcc_add_symbol(s, "recipeAddTarget", recipeAddTarget);
|
||||
tcc_add_symbol(s, "recipeMessage", recipeMessage);
|
||||
tcc_add_symbol(s, "utilCreateString", utilCreateString);
|
||||
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
|
||||
// Something bad happened.
|
||||
|
@ -89,8 +124,42 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
|||
return -3;
|
||||
}
|
||||
|
||||
getcwd(__utilFilenameBuffer, FILENAME_MAX);
|
||||
oldLocation = strdup(__utilFilenameBuffer);
|
||||
chdir(outputPath);
|
||||
|
||||
#if HAVE_SIGSEGV_RECOVERY
|
||||
sigset_t emptySet;
|
||||
|
||||
runPass = 0;
|
||||
|
||||
if (sigsegv_install_handler(&sigHandler) < 0)
|
||||
return -5;
|
||||
|
||||
sigemptyset(&emptySet);
|
||||
sigprocmask(SIG_BLOCK, &emptySet, &runSigSet);
|
||||
|
||||
switch (setjmp(runRecipe)) {
|
||||
case 0:
|
||||
result = entry(input, outputPath);
|
||||
case 1:
|
||||
sigprocmask(SIG_SETMASK, &runSigSet, NULL);
|
||||
sigsegv_install_handler(NULL);
|
||||
if (runPass != 0) {
|
||||
message(MSG_SEVERE, "%s caused a segmentation fault!", recipe);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
result = entry(input, outputPath);
|
||||
|
||||
#endif
|
||||
|
||||
chdir(oldLocation);
|
||||
DEL(oldLocation);
|
||||
|
||||
while (arrlen(___recipeTargets) > 0) {
|
||||
if (projectAddToTree(context, ___recipeTargets[0])) {
|
||||
utilSetDirty((WindowDataT *)context, TRUE);
|
||||
|
@ -106,6 +175,21 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
|||
}
|
||||
|
||||
|
||||
#if HAVE_SIGSEGV_RECOVERY
|
||||
static void sigHandlerContinuation(void *arg1, void *arg2, void *arg3) {
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
(void)arg3;
|
||||
longjmp(runRecipe, runPass);
|
||||
}
|
||||
|
||||
|
||||
int sigHandler(void *faultAddress, int serious) {
|
||||
runPass++;
|
||||
return sigsegv_leave_handler(sigHandlerContinuation, NULL, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void recipeAddTarget(char *target) {
|
||||
arrput(___recipeTargets, strdup(target));
|
||||
}
|
||||
|
|
|
@ -59,8 +59,8 @@ int main(int argc, char **argv) {
|
|||
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdnoreturn.h");
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tccdefs.h");
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tcclib.h");
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tgmath.h");
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/varargs.h");
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tgmath.h"); // Not needed.
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/varargs.h"); // Not needed.
|
||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/recipe.h");
|
||||
|
||||
winJoeyDevCreate();
|
||||
|
|
|
@ -48,7 +48,8 @@ void message(MessageTypesT level, char *format, ...) {
|
|||
GtkWidget *label;
|
||||
va_list args;
|
||||
char *string;
|
||||
char *temp;
|
||||
char *msg;
|
||||
char *tok;
|
||||
char *labels[MSG_COUNT] = {
|
||||
"<span foreground=\"gray\"> Info:</span>",
|
||||
"<span foreground=\"yellow\">Warning:</span>",
|
||||
|
@ -74,24 +75,31 @@ void message(MessageTypesT level, char *format, ...) {
|
|||
|
||||
// Display message.
|
||||
va_start(args, format);
|
||||
temp = utilCreateStringVArgs(format, args);
|
||||
msg = utilCreateStringVArgs(format, args);
|
||||
va_end(args);
|
||||
|
||||
string = utilCreateString("<tt>%s %s</tt>", labels[level], temp);
|
||||
// Break multiline messages down into individual lines.
|
||||
tok = strtok(msg, "\n");
|
||||
while (tok != NULL) {
|
||||
//***TODO*** Filter out things that could be mistaken as markup tags.
|
||||
string = utilCreateString("<tt>%s %s</tt>", labels[level], tok);
|
||||
|
||||
row = gtk_list_box_row_new();
|
||||
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,6);
|
||||
gtk_widget_set_hexpand(box, TRUE);
|
||||
label = gtk_label_new(string);
|
||||
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
|
||||
row = gtk_list_box_row_new();
|
||||
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_widget_set_hexpand(box, TRUE);
|
||||
label = gtk_label_new(string);
|
||||
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
|
||||
|
||||
DEL(string);
|
||||
DEL(string);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(row), box);
|
||||
gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1);
|
||||
gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(row), box);
|
||||
gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1);
|
||||
|
||||
gtk_widget_show_all(row);
|
||||
gtk_widget_show_all(row);
|
||||
|
||||
tok = strtok(NULL, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -180,6 +180,8 @@ EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData) {
|
|||
|
||||
(void)widget;
|
||||
|
||||
//***TODO*** This should be an embedded file.
|
||||
//***TODO*** We should also provide .gitignore and .gitattribute files.
|
||||
if (utilFileSaveOtherAs((WindowDataT *)userData, "*.c", "Recipe", &newFile)) {
|
||||
out = fopen(newFile, "wt");
|
||||
fprintf(out, ""
|
||||
|
@ -1090,6 +1092,8 @@ static gboolean updateBuildOptions(ProjectDataT *self) {
|
|||
result = TRUE;
|
||||
}
|
||||
|
||||
//***TODO*** Grab the latest joey.h
|
||||
|
||||
// Unload current target listing.
|
||||
backup = targetArrayCopy(self->targets);
|
||||
targetArrayDelete(&self->targets);
|
||||
|
|
BIN
thirdparty/libsigsegv-2.14.tar.gz
(Stored with Git LFS)
vendored
Normal file
BIN
thirdparty/libsigsegv-2.14.tar.gz
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
|
@ -154,12 +154,23 @@ pushd "${ROOT}" || exit &> /dev/null
|
|||
|
||||
if [[ ! -f ${INSTALLED}/lib/libtcc.a ]]; then
|
||||
echo Building Dependency: TinyCC...
|
||||
tar xzf ${THIRDPARTY}/tinycc-0.9.27.tar.bz2
|
||||
tar xjf ${THIRDPARTY}/tinycc-0.9.27.tar.bz2
|
||||
pushd tinycc-0.9.27 || exit &> /dev/null
|
||||
./configure \
|
||||
--prefix=${INSTALLED} \
|
||||
--enable-static \
|
||||
--with-libgcc
|
||||
--enable-static
|
||||
make
|
||||
make install
|
||||
popd || true &> /dev/null
|
||||
fi
|
||||
|
||||
if [[ ! -f ${INSTALLED}/lib/libsigsegv.a ]]; then
|
||||
echo Building Dependency: libsigsegv...
|
||||
tar xzf ${THIRDPARTY}/libsigsegv-2.14.tar.gz
|
||||
pushd libsigsegv-2.14 || exit &> /dev/null
|
||||
./configure \
|
||||
--prefix=${INSTALLED} \
|
||||
--enable-static
|
||||
make
|
||||
make install
|
||||
popd || true &> /dev/null
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<object class="GtkWindow" id="winMessages">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="title" translatable="yes">Messages</property>
|
||||
<property name="default-width">440</property>
|
||||
<property name="default-height">250</property>
|
||||
<property name="default-width">800</property>
|
||||
<property name="default-height">300</property>
|
||||
<signal name="delete-event" handler="winMessagesClose" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
|
|
Loading…
Add table
Reference in a new issue