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/libz.a
|
||||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
|
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
|
||||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.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)
|
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/libz.a
|
||||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
|
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
|
||||||
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.a
|
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.a
|
||||||
|
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libsigsegv.a
|
||||||
${GTK3_LIBRARIES}
|
${GTK3_LIBRARIES}
|
||||||
-ldl
|
-ldl
|
||||||
-pthread
|
-pthread
|
||||||
|
|
|
@ -24,11 +24,30 @@
|
||||||
|
|
||||||
|
|
||||||
#include <tcclib.h>
|
#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 char **___recipeTargets;
|
||||||
|
|
||||||
|
|
||||||
|
// 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 recipeAddTarget(char *target);
|
||||||
extern void recipeMessage(char *format, ...);
|
extern void recipeMessage(char *format, ...);
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,34 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "libtcc.h"
|
#include "libtcc.h"
|
||||||
|
#include "sigsegv.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "array.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;
|
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.
|
// All the paths passed in here are expected to be complete and absolute.
|
||||||
int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context) {
|
int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context) {
|
||||||
TCCState *s;
|
TCCState *s;
|
||||||
int result;
|
char *oldLocation;
|
||||||
|
char c;
|
||||||
|
int x;
|
||||||
|
int result = -255;
|
||||||
int (*entry)(char *, char *);
|
int (*entry)(char *, char *);
|
||||||
|
|
||||||
___recipeTargets = NULL;
|
___recipeTargets = NULL;
|
||||||
|
@ -60,9 +85,15 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
||||||
return -1;
|
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_set_lib_path(s, __resourcePath);
|
||||||
tcc_add_sysinclude_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_error_func(s, stdout, compilerErrorHandler);
|
||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||||
|
|
||||||
|
@ -72,9 +103,13 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcc_add_symbol(s, "fputc", fputc);
|
||||||
|
tcc_add_symbol(s, "qsort", qsort);
|
||||||
|
|
||||||
tcc_add_symbol(s, "___recipeTargets", ___recipeTargets);
|
tcc_add_symbol(s, "___recipeTargets", ___recipeTargets);
|
||||||
tcc_add_symbol(s, "recipeAddTarget", recipeAddTarget);
|
tcc_add_symbol(s, "recipeAddTarget", recipeAddTarget);
|
||||||
tcc_add_symbol(s, "recipeMessage", recipeMessage);
|
tcc_add_symbol(s, "recipeMessage", recipeMessage);
|
||||||
|
tcc_add_symbol(s, "utilCreateString", utilCreateString);
|
||||||
|
|
||||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
|
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
|
||||||
// Something bad happened.
|
// Something bad happened.
|
||||||
|
@ -89,7 +124,41 @@ int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context
|
||||||
return -3;
|
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);
|
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) {
|
while (arrlen(___recipeTargets) > 0) {
|
||||||
if (projectAddToTree(context, ___recipeTargets[0])) {
|
if (projectAddToTree(context, ___recipeTargets[0])) {
|
||||||
|
@ -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) {
|
void recipeAddTarget(char *target) {
|
||||||
arrput(___recipeTargets, strdup(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/stdnoreturn.h");
|
||||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tccdefs.h");
|
utilExtractResource("/com/kangaroopunch/joeydev/resources/tccdefs.h");
|
||||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tcclib.h");
|
utilExtractResource("/com/kangaroopunch/joeydev/resources/tcclib.h");
|
||||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/tgmath.h");
|
utilExtractResource("/com/kangaroopunch/joeydev/resources/tgmath.h"); // Not needed.
|
||||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/varargs.h");
|
utilExtractResource("/com/kangaroopunch/joeydev/resources/varargs.h"); // Not needed.
|
||||||
utilExtractResource("/com/kangaroopunch/joeydev/resources/recipe.h");
|
utilExtractResource("/com/kangaroopunch/joeydev/resources/recipe.h");
|
||||||
|
|
||||||
winJoeyDevCreate();
|
winJoeyDevCreate();
|
||||||
|
|
|
@ -48,7 +48,8 @@ void message(MessageTypesT level, char *format, ...) {
|
||||||
GtkWidget *label;
|
GtkWidget *label;
|
||||||
va_list args;
|
va_list args;
|
||||||
char *string;
|
char *string;
|
||||||
char *temp;
|
char *msg;
|
||||||
|
char *tok;
|
||||||
char *labels[MSG_COUNT] = {
|
char *labels[MSG_COUNT] = {
|
||||||
"<span foreground=\"gray\"> Info:</span>",
|
"<span foreground=\"gray\"> Info:</span>",
|
||||||
"<span foreground=\"yellow\">Warning:</span>",
|
"<span foreground=\"yellow\">Warning:</span>",
|
||||||
|
@ -74,13 +75,17 @@ void message(MessageTypesT level, char *format, ...) {
|
||||||
|
|
||||||
// Display message.
|
// Display message.
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
temp = utilCreateStringVArgs(format, args);
|
msg = utilCreateStringVArgs(format, args);
|
||||||
va_end(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();
|
row = gtk_list_box_row_new();
|
||||||
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,6);
|
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
|
||||||
gtk_widget_set_hexpand(box, TRUE);
|
gtk_widget_set_hexpand(box, TRUE);
|
||||||
label = gtk_label_new(string);
|
label = gtk_label_new(string);
|
||||||
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
|
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
|
||||||
|
@ -92,6 +97,9 @@ void message(MessageTypesT level, char *format, ...) {
|
||||||
gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1);
|
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;
|
(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)) {
|
if (utilFileSaveOtherAs((WindowDataT *)userData, "*.c", "Recipe", &newFile)) {
|
||||||
out = fopen(newFile, "wt");
|
out = fopen(newFile, "wt");
|
||||||
fprintf(out, ""
|
fprintf(out, ""
|
||||||
|
@ -1090,6 +1092,8 @@ static gboolean updateBuildOptions(ProjectDataT *self) {
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***TODO*** Grab the latest joey.h
|
||||||
|
|
||||||
// Unload current target listing.
|
// Unload current target listing.
|
||||||
backup = targetArrayCopy(self->targets);
|
backup = targetArrayCopy(self->targets);
|
||||||
targetArrayDelete(&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
|
if [[ ! -f ${INSTALLED}/lib/libtcc.a ]]; then
|
||||||
echo Building Dependency: TinyCC...
|
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
|
pushd tinycc-0.9.27 || exit &> /dev/null
|
||||||
./configure \
|
./configure \
|
||||||
--prefix=${INSTALLED} \
|
--prefix=${INSTALLED} \
|
||||||
--enable-static \
|
--enable-static
|
||||||
--with-libgcc
|
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
|
||||||
make install
|
make install
|
||||||
popd || true &> /dev/null
|
popd || true &> /dev/null
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
<object class="GtkWindow" id="winMessages">
|
<object class="GtkWindow" id="winMessages">
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="title" translatable="yes">Messages</property>
|
<property name="title" translatable="yes">Messages</property>
|
||||||
<property name="default-width">440</property>
|
<property name="default-width">800</property>
|
||||||
<property name="default-height">250</property>
|
<property name="default-height">300</property>
|
||||||
<signal name="delete-event" handler="winMessagesClose" swapped="no"/>
|
<signal name="delete-event" handler="winMessagesClose" swapped="no"/>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkScrolledWindow">
|
<object class="GtkScrolledWindow">
|
||||||
|
|
Loading…
Add table
Reference in a new issue