From fb45f7075afa033de27e358739cbda0107af12b2 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 20 Jun 2017 08:48:14 -0700 Subject: [PATCH] Fix crash when built by GNU Gold linker on x86 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Problem reported by Andrés Musetti (Bug#27248). * src/widget.c (emacsFrameClassRec): Do not initialize superclass here. (emacsFrameClass): Now a function (which initializes the superclass) instead of a variable. All uses changed. --- src/unexelf.c | 12 +++++++++++- src/widget.c | 13 +++++++++++-- src/widget.h | 2 +- src/xfns.c | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/unexelf.c b/src/unexelf.c index 7fad64fab17..5129784ade2 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -576,7 +576,17 @@ unexec (const char *new_name, const char *old_name) } /* This loop seeks out relocation sections for the data section, so - that it can undo relocations performed by the runtime loader. */ + that it can undo relocations performed by the runtime loader. + + The following approach does not work on x86 platforms that use + the GNU Gold linker, which can generate .rel.dyn relocation + sections containing R_386_32 entries that the following code does + not grok. Emacs works around this problem by avoiding C + constructs that generate such entries, which is horrible hack. + + FIXME: Presumably more problems like this will crop up as linkers + get fancier. We really need to stop assuming that Emacs can grok + arbitrary linker output. See Bug#27248. */ for (n = new_file_h->e_shnum; 0 < --n; ) { ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n); diff --git a/src/widget.c b/src/widget.c index d7ec7028517..585039d58c6 100644 --- a/src/widget.c +++ b/src/widget.c @@ -108,7 +108,7 @@ emacsFrameTranslations [] = "\ static EmacsFrameClassRec emacsFrameClassRec = { { /* core fields */ - /* superclass */ &widgetClassRec, + /* superclass */ 0, /* filled in by emacsFrameClass */ /* class_name */ (char *) "EmacsFrame", /* widget_size */ sizeof (EmacsFrameRec), /* class_initialize */ 0, @@ -146,7 +146,16 @@ static EmacsFrameClassRec emacsFrameClassRec = { } }; -WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec; +WidgetClass +emacsFrameClass (void) +{ + /* Set the superclass here rather than relying on static + initialization, to work around an unexelf.c bug on x86 platforms + that use the GNU Gold linker (Bug#27248). */ + emacsFrameClassRec.core_class.superclass = &widgetClassRec; + + return (WidgetClass) &emacsFrameClassRec; +} static void get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height) diff --git a/src/widget.h b/src/widget.h index 2c5fb61df2f..97dd6ab61de 100644 --- a/src/widget.h +++ b/src/widget.h @@ -90,7 +90,7 @@ along with GNU Emacs. If not, see . */ typedef struct _EmacsFrameRec *EmacsFrame; typedef struct _EmacsFrameClassRec *EmacsFrameClass; -extern WidgetClass emacsFrameClass; +extern WidgetClass emacsFrameClass (void); extern struct _DisplayContext *display_context; diff --git a/src/xfns.c b/src/xfns.c index e463391c74a..7be2253cc3b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2875,7 +2875,7 @@ x_window (struct frame *f, long window_prompting) XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; XtSetArg (al[ac], XtNborderWidth, 0); ac++; - frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget, + frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget, al, ac); f->output_data.x->edit_widget = frame_widget; -- 2.39.2