This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Store each function in a different section when compiled into an ELF file

Can it be done ?

I just read a post on the forum and it would be extremely helpful for me.

Arc

You'll need to put the function into its own section

Is there any compile argument to do so ?

Thank you.

  • Jon Zarate said:
    Is there any compile argument to do so ?

    Yes, the compiler option is --gen_func_subsections.

    For more details, please see the Compiler Users Guide for the processor family you are working with.

  • I just tried it but it is not working. I have the same amount of sections.

    I added the following line to the compiler options : --gen_func_subsections=on

    I checked in the options just in case I was writing it wrong or something, but the option is not working in the GUI. The options are not shown.

    If you try to set a value, the list box is empty. So this is how the options of my compiler look like:

    Thank you in advance.

  • Jon,

    For the MSP430, looks this option is being set by default by the compiler. If you take a look at the link map file after the build and see sections named like (.text:name_of_function) for each function, then the option is already enabled. If the option were not turned on, the sections would be just (.text) without the function name appended.

  • I just have 2 .text functions: .text and .text:_isr. This is the output.

    --------------- ELF SECTION HEADER (97) ---------------
     Idx  Name                  Size      VMA       LMA       File off  Algn  EntSize   Info Type     Flags
      0.                        0         0         0         0         0     0         0    0        0        (0)
      1.  .bss                  2         2400      2400      34        2     0         0    8        3        (3)
      2.  .data                 0         0         0         1a2       1     0         0    8        3        (3)
      3.  .TI.noinit            0         0         0         0         1     0         0    8        268435456 (10000000)
      4.  .sysmem               0         0         0         0         1     0         0    8        0        (0)
      5.  .stack                160       4360      4360      34        4     0         0    8        3        (3)
      6.  .text:_isr            66        4400      4400      34        2     0         0    1        6        (6)
      7.  .cinit                18        4442      4442      76        2     0         0    1        2        (2)
      8.  .const                0         0         0         0         1     0         0    8        0        (0)
      9.  .cio                  0         0         0         0         1     0         0    8        0        (0)
     10.  .pinit                0         0         0         0         1     0         0    8        0        (0)
     11.  .init_array           0         0         0         1a2       1     0         0    8        3        (3)
     12.  .mspabi.exidx         0         0         0         1a2       1     8         0    8        130      (82)
     13.  .mspabi.extab         0         0         0         1a2       1     0         0    8        2        (2)
     14.  .infoA                0         0         0         0         1     0         0    8        0        (0)
     15.  .infoB                0         0         0         0         1     0         0    8        0        (0)
     16.  .infoC                0         0         0         0         1     0         0    8        0        (0)
     17.  .infoD                0         0         0         0         1     0         0    8        0        (0)
     18.  .int00                0         0         0         0         1     0         0    8        0        (0)
     19.  .int01                0         0         0         0         1     0         0    8        0        (0)
     20.  .int02                0         0         0         0         1     0         0    8        0        (0)
     21.  .int03                0         0         0         0         1     0         0    8        0        (0)
     22.  .int04                0         0         0         0         1     0         0    8        0        (0)
     23.  .int05                0         0         0         0         1     0         0    8        0        (0)
     24.  .int06                0         0         0         0         1     0         0    8        0        (0)
     25.  .int07                0         0         0         0         1     0         0    8        0        (0)
     26.  .int08                0         0         0         0         1     0         0    8        0        (0)
     27.  .int09                0         0         0         0         1     0         0    8        0        (0)
     28.  .int10                0         0         0         0         1     0         0    8        0        (0)
     29.  .int11                0         0         0         0         1     0         0    8        0        (0)
     30.  .int12                0         0         0         0         1     0         0    8        0        (0)
     31.  .int13                0         0         0         0         1     0         0    8        0        (0)
     32.  .int14                0         0         0         0         1     0         0    8        0        (0)
     33.  .int15                0         0         0         0         1     0         0    8        0        (0)
     34.  .int16                0         0         0         0         1     0         0    8        0        (0)
     35.  .int17                0         0         0         0         1     0         0    8        0        (0)
     36.  .int18                0         0         0         0         1     0         0    8        0        (0)
     37.  .int19                0         0         0         0         1     0         0    8        0        (0)
     38.  .int20                0         0         0         0         1     0         0    8        0        (0)
     39.  .int21                0         0         0         0         1     0         0    8        0        (0)
     40.  .int22                0         0         0         0         1     0         0    8        0        (0)
     41.  .int23                0         0         0         0         1     0         0    8        0        (0)
     42.  .int24                0         0         0         0         1     0         0    8        0        (0)
     43.  .int25                0         0         0         0         1     0         0    8        0        (0)
     44.  .int26                0         0         0         0         1     0         0    8        0        (0)
     45.  .int27                0         0         0         0         1     0         0    8        0        (0)
     46.  .int28                0         0         0         0         1     0         0    8        0        (0)
     47.  .int29                0         0         0         0         1     0         0    8        0        (0)
     48.  .int30                0         0         0         0         1     0         0    8        0        (0)
     49.  .int31                0         0         0         0         1     0         0    8        0        (0)
     50.  .int32                0         0         0         0         1     0         0    8        0        (0)
     51.  .int33                0         0         0         0         1     0         0    8        0        (0)
     52.  .int34                0         0         0         0         1     0         0    8        0        (0)
     53.  .int35                0         0         0         0         1     0         0    8        0        (0)
     54.  .int36                0         0         0         0         1     0         0    8        0        (0)
     55.  .int37                0         0         0         0         1     0         0    8        0        (0)
     56.  .int38                0         0         0         0         1     0         0    8        0        (0)
     57.  .int39                0         0         0         0         1     0         0    8        0        (0)
     58.  .int40                0         0         0         0         1     0         0    8        0        (0)
     59.  RTC                   2         ffd2      ffd2      88        1     0         0    1        2        (2)
     60.  PORT2                 2         ffd4      ffd4      8a        1     0         0    1        2        (2)
     61.  TIMER2_A1             2         ffd6      ffd6      8c        1     0         0    1        2        (2)
     62.  TIMER2_A0             2         ffd8      ffd8      8e        1     0         0    1        2        (2)
     63.  USCI_B1               2         ffda      ffda      90        1     0         0    1        2        (2)
     64.  USCI_A1               2         ffdc      ffdc      92        1     0         0    1        2        (2)
     65.  PORT1                 2         ffde      ffde      94        1     0         0    1        2        (2)
     66.  TIMER1_A1             2         ffe0      ffe0      96        1     0         0    1        2        (2)
     67.  TIMER1_A0             2         ffe2      ffe2      98        1     0         0    1        2        (2)
     68.  DMA                   2         ffe4      ffe4      9a        1     0         0    1        2        (2)
     69.  USB_UBM               2         ffe6      ffe6      9c        1     0         0    1        2        (2)
     70.  TIMER0_A1             2         ffe8      ffe8      9e        1     0         0    1        2        (2)
     71.  TIMER0_A0             2         ffea      ffea      a0        1     0         0    1        2        (2)
     72.  ADC12                 2         ffec      ffec      a2        1     0         0    1        2        (2)
     73.  USCI_B0               2         ffee      ffee      a4        1     0         0    1        2        (2)
     74.  USCI_A0               2         fff0      fff0      a6        1     0         0    1        2        (2)
     75.  WDT                   2         fff2      fff2      a8        1     0         0    1        2        (2)
     76.  TIMER0_B1             2         fff4      fff4      aa        1     0         0    1        2        (2)
     77.  TIMER0_B0             2         fff6      fff6      ac        1     0         0    1        2        (2)
     78.  COMP_B                2         fff8      fff8      ae        1     0         0    1        2        (2)
     79.  UNMI                  2         fffa      fffa      b0        1     0         0    1        2        (2)
     80.  SYSNMI                2         fffc      fffc      b2        1     0         0    1        2        (2)
     81.  .reset                2         fffe      fffe      b4        2     0         0    1        2        (2)
     82.  .TI.persistent        0         0         0         0         1     0         0    8        268435456 (10000000)
     83.  .debug_info           5575      0         0         1a2       1     0         0    1        0        (0)
     84.  .debug_line           1330      0         0         1769      1     0         0    1        0        (0)
     85.  .debug_frame          670       0         0         1c9b      1     0         0    1        0        (0)
     86.  .debug_abbrev         1410      0         0         1f39      1     0         0    1        0        (0)
     87.  .debug_str            923       0         0         24bb      1     0         0    1        0        (0)
     88.  .debug_aranges        320       0         0         2856      1     0         0    1        0        (0)
     89.  .debug_pubname        411       0         0         2996      1     0         0    1        0        (0)
     90.  .debug_pubtype        390       0         0         2b31      1     0         0    1        0        (0)
     91.  .text                 236       10000     10000     b6        2     0         0    1        6        (6)
     92.  __TI_build_att        132       0         0         2cb7      0     0         0    1879048195 0        (0)
     93.  .symtab               17920     0         0         2d3c      0     16        325  2        0        (0)
     94.  .TI.section.fl        26        0         0         733c      0     0         0    2130706437 0        (0)
     95.  .strtab               9469      0         0         7356      0     1         0    3        32       (20)
     96.  .shstrtab             802       0         0         9853      0     1         0    3        32       (20)

    Any clues ?

    EDIT: I add the code and map section regarding .text just in case:

    #include <msp430.h> 
    
    /*
     * main.c
     */
    
    unsigned int turn;
    
    int main(void) {
    
    	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
    	P4DIR |= BIT7;
    	P1DIR |= BIT0;
    
    	TA0CCTL0 |= CCIE; //Enable Interrupts on Timer
    	TA0CCR0 = 6000; //Number of cycles in the timer
    	TA0CTL |= TASSEL_1; //Use ACLK as source for timer
    	TA0CTL |= MC_1; //Use UP mode timer
    
    	turn = 1;
    
    	__enable_interrupt();
    
    	__bis_SR_register(LPM0 + GIE); // LPM0 with interrupts enabled
    
    
    	return 0;
    }
    
    void green_on (){
    	P4OUT |= BIT7;
    }
    
    void green_off (){
    	P4OUT &= 0x7F;
    }
    
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A0(void) {
    
    	if ( turn == 0 ){
    		green_off();
    		turn = 1;
    	}else{
    		green_on();
    		turn = 0;
    	}
    	P1OUT ^= BIT0;
    
    }


    .text      0    00010000    000000ec     
                      00010000    0000006c     rts430x_lc_rd_eabi.lib : autoinit_wdt.obj (.text:_auto_init_hold_wdt)
                      0001006c    00000044     main.obj (.text:main)
                      000100b0    00000024     rts430x_lc_rd_eabi.lib : copy_zero_init.obj (.text:decompress:ZI:__TI_zero_init)
                      000100d4    00000008     main.obj (.text:green_off)
                      000100dc    00000008     main.obj (.text:green_on)
                      000100e4    00000004     rts430x_lc_rd_eabi.lib : pre_init.obj (.text:_system_pre_init)
                      000100e8    00000004                            : exit.obj (.text:abort)

  • The linker collapses the various .text:one, .text:two, etc, into a single .text. This is controlled by the linker command file. You are looking at the "output sections" in the executable object file. The linker map shows you that the "input sections" do in fact have subsections (e.g. .text:main). However, the input sections are gone in the executable object file.

    The option -gen_func_subsections only controls whether the compiler generates subsections. it does not affect the linker.
  • I understand... Is there any way (linker argument) to keep those subsections also in the output ELF file ?
  • There is no linker argument to do so. You could do it by hand by editing the linker map file to place each input section individually, although this would be quite a pain.
  • Can you think of any way to divide the functions in .text ? Maybe using symbols ? It would be a really nice feature regarding security.

    Thank you.

  • Make sure that all of your "secret" functions are in separate subsections coming out of the compiler (--gen_func_subsections=on). In the linker command file, make a distinct .text:secret output section in your linker command file and allocate all of the "secret" .text input subsections in that output section.
  • (1) Isn't that the same as you suggested in your previous post ?

    Also, if possible, (2) I would like to know if there is any generic solution for it, instead of editing every new project depending on it's functions.

    (3) Or maybe find a way to automatize this tedious process ?

    Thank you.

    EDIT: my boss suggested dividing the functions on run-time using the debug information. (4) Would that  be possible ? Is the needed information in there ?

  • Jon Zarate said:
    (1) Isn't that the same as you suggested in your previous post ?

    Yes

    Jon Zarate said:
    (2) I would like to know if there is any generic solution for it

    Unfortunately, no.

    Jon Zarate said:
    (3) Or maybe find a way to automatize this tedious process ?

    It's possible.  But you are on your own.  Here is one idea to consider.  Install the cg_xml package.  Nothing in there solves your problem.  But the Perl source code gives you a starting point.  Take a look at the Perl code in map/lib_footprint.pl .  Find the loop where it goes through the input sections.  Your solution would use similar code.  The idea is to auto-generate a linker command file that does nothing but create the output sections that have the same name as the .text:name_of_function input sections. This file would look similar to this ...

    SECTIONS {
       .text:function_one > FLASH
       .text:function_two > FLASH
       .text:function_three > FLASH
       /* and so on */
    }

    Add this auto-generated linker command file to the files processed by the linker.  Note it is OK to have multiple linker command files, and multiple SECTIONS directives from those different linker command files.

    Thanks and regards,

    -George

  • I will check it right now, meanwhile, it would be very helpful to know if it can be done with debug information (as asked in question 4).

    Thank you.

    EDIT: I just saw code :

    It looks like it is defining the .text:_isr section there, (1) is it ? (2) Could I do that for my functions ?

    Regarding the stack initialization, it declares the global __STACK_END and immediately uses it. If I wanted to relocate this program I would just have to assign a value to __STACK_END symbol, since the value of the symbol is 0, (3) right ?

    Symbol table '.symtab' contains 1431 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
      1423: 00000000     0 NOTYPE  GLOBAL HIDDEN   UND __STACK_END

  • 1) No; this is a definition of the macro CSTART_DECL, which will be used later for a declaration of a function in section .text:_isr
    2) Sure, you can set the text section of any C function with the GCC-style attribute "section", as long as the declaration with the attribute is visible where the function is actually defined.
    3) __STACK_END is special; I don't know immediately what you'd have to do to handle it.
  • (1) Then, if I add 10 sections to my linker script (section0, section1 ...) and I have 10 code files, could I use this section attribute to store each file's code/functions in different places right ?

    Also, there is a question that I would like to ask again. (2)  Can I divide the .text section data by functions using the debug information (as asked in this post) ?

    Thank you.

  • 1) There are two steps. Step one, you must instruct the linker to put functions into a distinct subsection. You can do this with GCC attribute "section", with pragma CODE_SECTION, or --gen_func_subsections=on. Step two, you must use the linker command file to give selected input sections (not functions) special treatment. For each set of "secret" functions that you want to handle in the same way, you could give them all the same section name (e.g. ".text:secret_function_set_1") and then only need to add one line per secret function set to the linker command file. It is irrelevant how many sections or source files are involved.

    2) The linker deals with sections, not functions. The linker cannot "see" the functions. There is no mechanism anywhere in the TI toolset to slice sections into smaller units after the object file has been created. In theory, I suppose you might be able to use the debugging information to find the boundaries of functions and create new object files with each function in its own section, but this would be incredibly difficult, and you are much better off having the compiler put each function in its own subsection to begin with, and using the linker command file to place each such input section into its own output section, however tedious that might be.
  • (1) The method used in (1) is the same as you suggested using with all functions in this post, right ? Just less work to do dividing by files instead.

    (2) I think I didn't explain it correctly. I meant using the debug information in the ELF file (-g argument used). An ELF file has lots of debug sections, is there any information I could use to divide by functions ?

  • 1) yes
    2) I understood that you meant the DWARF debug information in the ELF file. My answer stands.
  • Could you provide some documentation on the debug information in the ELF file ? What information is saved, how etc.

    Thanks.
  • This wiki article is a start.

    Do you still intend to use Dwarf debug info to extract functions from within .text input sections?  I'll repeat what Archaeologist said, but in a different way.  Dwarf is not designed for that purpose.  Use the compiler feature for putting each function in a sub-section.

    Thanks and regards,

    -George

  • I understood, but I need to know the reasons behind, what information is saved, how and why it is not possible to read it from there.

    I will likely do it as Archaeologist said, but I can't just argue that "it's not designed for that purpose'. Hope it makes sense.

    Thanks.
  • Follow the links in the wiki article to the DWARF standard. It will tell you everything you need to know to interpret the DWARF sections.

    We're warning you now that that approach is a dead end. You are trying to unbake a cookie to remove the raisins and substitute nuts. While it is theoretically possible to re-arrange the atoms, you are far, far better off making a new batch of cookies the right way to begin with.

    The argument you should be using is cost, particularly development cost. The compiler experts are telling you that it will be one or two orders of magnitude more difficult (if it is even possible!) to design a way to correctly pick apart the functions via the DWARF information than to annotate the source code with code section attributes. Then ask if you want to pursue a novel technique that the experts are telling you will be very costly to develop, completely unsupported by the compiler, and unlikely to work all the time. Or to annotate the source, which is supported and works?
  • Don't get me wrong, I will do it as you both suggested me to do it, but I need to know why it is not possible and if I am asked why I didn't use the debug information, be able to tell the reasons apart from the cost. I need the be able to tell them about the "viability", I mean, why it's not a good idea, like maybe some information is missing or something like that.

    That's why I need to have a look at it. However, I am not using it, thanks to you it's clear for me it's not worth.