Bug 92902 - jump tables are put into the text section
Summary: jump tables are put into the text section
Status: SUSPENDED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 9.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-12-10 22:45 UTC by Jean-Christophe Dubois
Modified: 2023-05-18 08:52 UTC (History)
4 users (show)

See Also:
Host:
Target: sparc*-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-12-11 00:00:00


Attachments
assembly file with jump tables in the text section (8.17 KB, text/plain)
2019-12-11 19:35 UTC, Jean-Christophe Dubois
Details
Tentative fix (645 bytes, patch)
2019-12-11 21:34 UTC, Eric Botcazou
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jean-Christophe Dubois 2019-12-10 22:45:14 UTC
gcc 9.2 (and maybe other versions) is putting jump table directly in the text section.

On most processors I guess this is not an issue as the text section is usually readable.

But on some processors like (like the SPARC processor) this is an issue when user space text section is protected (from the OS) with an "eXecute Only" MMU protection.

In such case when the code is trying to read the jump table from the text section, a data abort exception is generated and the all application is crashed.

To work around the problem I have to either:
* change the protection (from the OS) on the text segment to "Read and eXecute"
* compile with the -fno-jump-table command line option.

These 2 work arroud allow the application code (that use to work OK on gcc 8 and gcc 7) to run again when comiled with gcc 9

I believe the jump_table should go in the ro_data section. Putting them in the text section seems wrong. A jump table is data after all.

Another solution is to avoid generating "jump tables" on processors/architecture that could put "eXecute Only" MMU protection on text segments.

On SPARC/LEON there is also the -muser_mode command line option that could be used to avoid generating jump tables if it is not possible to move them in the ro_data section.
Comment 1 Andrew Pinski 2019-12-10 22:49:01 UTC
This is a target specific issue.  That is each target decides where to put the jump table.  On some targets, it is already done not in the text section but the rodata section.  It seems like sparc is not one of those.  the SPARC back-end does not get much attention these days as oracle has moved away from sparc really.
Comment 2 Eric Botcazou 2019-12-11 10:01:32 UTC
Nothing has changed in GCC 9.x and this is also visible with GCC 7 & 8, although the SPARC port is configured with JUMP_TABLES_IN_TEXT_SECTION set to 0.
Comment 3 Eric Botcazou 2019-12-11 10:12:08 UTC
The decision dates back to the rewrite of the SPARC port in 1998:

21652      davem   /* Align to cache line in the function's code section.  */
21652      davem   function_section (current_function_decl);
Comment 4 Jean-Christophe Dubois 2019-12-11 19:35:47 UTC
Created attachment 47475 [details]
assembly file with jump tables in the text section
Comment 5 Jean-Christophe Dubois 2019-12-11 19:36:31 UTC
I guess JUMP_TABLES_IN_TEXT_SECTION is supposed to mean that the "jump tables" should not be put in the text section.

However something is wrong then because gcc 9 (and maybe previous) is putting the jump table as a "subsection" of the text section in the generated assembly code (therefore it is part of the text section).

I am attaching a generated assembly file where "jump tables" are generated and declared as subsection of the text section. In this file you can for example look at the L87 jump table which is used by the tfp_format function (this is the first jump table that triggered an exception in my test case).

So assuming the intend is to put the jump table in the rodata section, something seems to be broken in the build then.
Comment 6 Eric Botcazou 2019-12-11 19:48:29 UTC
> So assuming the intend is to put the jump table in the rodata section,
> something seems to be broken in the build then.

No, see my earlier remark, this was intended.
Comment 7 Eric Botcazou 2019-12-11 19:50:05 UTC
DaveM, any recollection about the rationale for the decision?
Comment 8 davem 2019-12-11 20:41:00 UTC
I cannot think of any specific reason why the jump tables were put into the text section.  I even tried to consider relocation ramifications.

Maybe this makes GOT OP linker optimizations more likely when -fPIC?
Comment 9 Eric Botcazou 2019-12-11 21:15:16 UTC
> I cannot think of any specific reason why the jump tables were put into the
> text section.  I even tried to consider relocation ramifications.

Yes, relocation considerations quickly come to mind.  Thanks in any case.

> Maybe this makes GOT OP linker optimizations more likely when -fPIC?

I wonder whether this wouldn't stem from limitations of the Sun assembler or somesuch: in PIC mode, this would generate differences between labels from different sections, so relocations need to be generated by the assembler.
Comment 10 Eric Botcazou 2019-12-11 21:17:39 UTC
The SPARC port even has a specific implementation here:

/* This is how we hook in and defer the case-vector until the end of
   the function.  */
#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
  sparc_defer_case_vector ((LAB),(VEC), 0)

#define ASM_OUTPUT_ADDR_DIFF_VEC(LAB,VEC) \
  sparc_defer_case_vector ((LAB),(VEC), 1)
Comment 11 Eric Botcazou 2019-12-11 21:34:11 UTC
Created attachment 47476 [details]
Tentative fix
Comment 12 davem 2019-12-11 22:19:35 UTC
I think that case vector stuff was written by Richard Henderson FWIW.
Comment 13 Eric Botcazou 2019-12-11 22:33:21 UTC
> I think that case vector stuff was written by Richard Henderson FWIW.

Richard, do you have any recollection of this?
Comment 14 Richard Henderson 2019-12-11 23:57:47 UTC
The only reason I can think for jump tables to be put into the text
section is the old aout format, which didn't have a separate read
only data section.  There should be no reason to do that these days.
Comment 15 Jean-Christophe Dubois 2019-12-12 20:10:47 UTC
Thanks for the feedback and the support.

Now maybe this is not the good place to ask question but I am wondering:

Most of today's processors have separate data and instruction cache. Isn't it sub optimal performance wise to load the instruction cache with jump tables (just data consuming precious cache resource) and then having to load these same jump tables again in the data cache to use them (jump tables might then be loaded twice and eat instruction cache for no reason).

If there were only processors with unified cache this would not be an issue but this is not the most common case in today's processors.

Am I missing something? Shouldn't most architecture put jump tables in rodata section.

Thanks

JC
Comment 16 Andrew Pinski 2019-12-12 20:32:40 UTC
(In reply to Jean-Christophe Dubois from comment #15)
> Am I missing something? 

YES.  Most likely it will not be loaded in the instruction cache as it is larger than the cache line size.
Comment 17 Mikael Pettersson 2019-12-12 22:59:21 UTC
My though reading this is that most RICSs have problems synthesizing large literals, so putting a jump table in .text might increase the likelihood of its address being synthesizable with a PC + offset addressing mode.  Putting it in .rodata would almost certainly require you to indirect through the GOT to address it.  That said, if the user wants .text to be execute-only, then the jump table ought to land in .rodata.
Comment 18 Jean-Christophe Dubois 2019-12-14 07:59:45 UTC
(In reply to Mikael Pettersson from comment #17)
> My though reading this is that most RICSs have problems synthesizing large
> literals, so putting a jump table in .text might increase the likelihood of
> its address being synthesizable with a PC + offset addressing mode.  Putting
> it in .rodata would almost certainly require you to indirect through the GOT
> to address it.  That said, if the user wants .text to be execute-only, then
> the jump table ought to land in .rodata.

As far as I can say with the assembly code generated today for SPARC32, the jump tables could be anywhere in memory (4GB address space) with the exact same code. I don't think it would trigger additional indirection.

It might be different for other architecture.
Comment 19 Jean-Christophe Dubois 2019-12-14 15:16:49 UTC
(In reply to Andrew Pinski from comment #16)
> (In reply to Jean-Christophe Dubois from comment #15)
> > Am I missing something? 
> 
> YES.  Most likely it will not be loaded in the instruction cache as it is
> larger than the cache line size.

Maybe this is not a big issue but couldn't the end of the jump table be loaded in instruction cache (depending on function alignment) with the beginning of the function it will be used with (when code is compiled with -Os functions don't seem to be aligned on cache line size)

Or the beginning of the jump table with the end of the previous function.

This might be only few bytes of instruction cache each time and maybe it is not an issue overall.

And when you mix data and code there will also be some instruction that will enter the data cache if things are not aligned on cache line size.

Maybe this is not an issue performance wise either.
Comment 20 Jakub Jelinek 2020-03-04 09:43:51 UTC
GCC 8.4.0 has been released, adjusting target milestone.
Comment 21 Eric Botcazou 2023-05-18 08:52:37 UTC
Probably too late to be changed now.