title: How does objcopy compute what sections for the elf file to insert into the output file?
body: <p>let's say I run <code>arm-none-eabi-objcopy firmwared.elf -O ihex firmware.hex</code></p>
  
  <p>Assume the binary was generated with the following linker script:</p>
  
  <pre><code>ENTRY(Reset_Handler)
  
  MEMORY
  {
    FLASH (RX) : ORIGIN = 0x08020000, LENGTH = 896K
    SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 512K
    BKPSRAM (RW) : ORIGIN = 0x40024000, LENGTH = 4K
  }
  
  _estack = 0x20080000;
  
  SECTIONS
  {
    .isr_vector :
    {
      . = ALIGN(4);
      _isr_vector = .;
      KEEP(*(.isr_vector))
      . = ALIGN(4);
    } &gt; FLASH
  
    .firmware_header_vector :
    {
      . = ALIGN(4);
      KEEP(*(.firmware_header_vector))
      . = ALIGN(4);
    } &gt; FLASH
  
    .text :
    {
      . = ALIGN(4);
      _stext = .;
      *(.Reset_Handler)
      *(.text)
      *(.text*)
      *(.rodata)
      *(.rodata*)
      *(.glue_7)
      *(.glue_7t)
      KEEP(*(.init))
      KEEP(*(.fini))
      . = ALIGN(4);
      _etext = .;
  
    } &gt; FLASH
  
    .ARM.extab :
    {
      . = ALIGN(4);
      *(.ARM.extab)
      *(.gnu.linkonce.armextab.*)
      . = ALIGN(4);
    } &gt; FLASH
  
    .exidx :
    {
      . = ALIGN(4);
      PROVIDE(__exidx_start = .);
      *(.ARM.exidx*)
      . = ALIGN(4);
      PROVIDE(__exidx_end = .);
    } &gt; FLASH
  
    .preinit_array :
    {
      PROVIDE(__preinit_array_start = .);
      KEEP(*(.preinit_array*))
      PROVIDE(__preinit_array_end = .);
    } &gt; FLASH
  
    .init_array :
    {
      PROVIDE(__init_array_start = .);
      KEEP(*(SORT(.init_array.*)))
      KEEP(*(.init_array*))
      PROVIDE(__init_array_end = .);
    } &gt; FLASH
  
    .fini_array :
    {
      PROVIDE(__fini_array_start = .);
      KEEP(*(.fini_array*))
      KEEP(*(SORT(.fini_array.*)))
      PROVIDE(__fini_array_end = .);
    } &gt; FLASH
  
    _sidata = .;
    .data_x : AT(_sidata) /* LMA address is _sidata (in FLASH) */
    {
      . = ALIGN(4);
      _sdata = .; /* data section VMA address */
      *(.data*)
      . = ALIGN(4);
      _edata = .;
    } &gt; SRAM
  
    .firmware_header (_sidata + SIZEOF(.data_x)):
    {
      . = ALIGN(4);
      KEEP(*(.firmware_header))
      . = ALIGN(4);
    } &gt; FLASH
  
    .eth (NOLOAD) :
    {
      . = ALIGN(4);
      KEEP(*(.RxDecripSection))
      KEEP(*(.TxDescripSection))
      KEEP(*(.RxarraySection))
      KEEP(*(.TxarraySection))
      . = ALIGN(4);
    } &gt; SRAM
  
    .bss :
    {
      . = ALIGN(4);
      _sbss = .;
  
      PROVIDE(__bss_start__ = _sbss);
      *(.bss)
      *(.bss*)
      *(COMMON)
      . = ALIGN(4);
      _ebss = .;
  
      PROVIDE(__bss_end__ = _ebss);
    } &gt; SRAM
  
    PROVIDE(end = .);
  
    .heap (NOLOAD) :
    {
      . = ALIGN(4);
      PROVIDE(__heap_start__ = .);
      KEEP(*(.heap))
      . = ALIGN(4);
      PROVIDE(__heap_end__ = .);
    } &gt; SRAM
  
    .reserved_for_stack (NOLOAD) :
    {
      . = ALIGN(4);
      PROVIDE(__reserved_for_stack_start__ = .);
      KEEP(*(.reserved_for_stack))
      . = ALIGN(4);
      PROVIDE(__reserved_for_stack_end__ = .);
    } &gt; SRAM
  
    .battery_backed_sram (NOLOAD) :
    {
      . = ALIGN(4);
      KEEP(*(.battery_backed_sram))
      . = ALIGN(4);
    } &gt; BKPSRAM
  
    /DISCARD/ :
    {
      *(.ARM.attributes)
    }
  }
  </code></pre>
  
  <p>This results in a readelf output of:</p>
  
  <pre><code>Section Headers:
    [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
    [ 0]                   NULL            00000000 000000 000000 00      0   0  0
    [ 1] .isr_vector       PROGBITS        08020000 010000 0001f8 00  WA  0   0  4
    [ 2] .firmware_header_ PROGBITS        080201f8 0101f8 000004 00  WA  0   0  4
    [ 3] .text             PROGBITS        08020200 010200 021b44 00  AX  0   0 64
    [ 4] .ARM.extab        PROGBITS        08041d44 042728 000000 00   W  0   0  1
    [ 5] .exidx            ARM_EXIDX       08041d44 031d44 000008 00  AL  3   0  4
    [ 6] .init_array       INIT_ARRAY      08041d4c 031d4c 000008 04  WA  0   0  4
    [ 7] .fini_array       FINI_ARRAY      08041d54 031d54 000004 04  WA  0   0  4
    [ 8] .data_x           PROGBITS        20000000 040000 0009c8 00  WA  0   0  8
    [ 9] .firmware_header  PROGBITS        08042720 042720 000008 00  WA  0   0  4
    [10] .eth              NOBITS          200009c8 0509c8 0030a0 00  WA  0   0  4
    [11] .bss              NOBITS          20003a68 0509c8 045da4 00  WA  0   0  4
    [12] .heap             PROGBITS        2004980c 042728 000000 00   W  0   0  1
    [13] .reserved_for_sta PROGBITS        2004980c 042728 000000 00   W  0   0  1
    [14] .battery_backed_s NOBITS          40024000 044000 00000c 00  WA  0   0  4
    [15] .comment          PROGBITS        00000000 042728 000075 01  MS  0   0  1
    [16] .debug_frame      PROGBITS        00000000 0427a0 00144c 00      0   0  4
    [17] .stab             PROGBITS        00000000 043bec 000084 0c     18   0  4
    [18] .stabstr          STRTAB          00000000 043c70 000117 00      0   0  1
    [19] .symtab           SYMTAB          00000000 043d88 009b00 10     20 1787  4
    [20] .strtab           STRTAB          00000000 04d888 0042bb 00      0   0  1
    [21] .shstrtab         STRTAB          00000000 051b43 0000e6 00      0   0  1
  Key to Flags:
    W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
    L (link order), O (extra OS processing required), G (group), T (TLS),
    C (compressed), x (unknown), o (OS specific), E (exclude),
    y (purecode), p (processor specific)
  
  There are no section groups in this file.
  
  Program Headers:
    Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
    LOAD           0x010000 0x08020000 0x08020000 0x21d58 0x21d58 RWE 0x10000
    LOAD           0x040000 0x20000000 0x08041d58 0x009c8 0x009c8 RW  0x10000
    LOAD           0x042720 0x08042720 0x08042720 0x00008 0x00008 RW  0x10000
    LOAD           0x0509c8 0x200009c8 0x08042720 0x00000 0x48e44 RW  0x10000
    LOAD           0x044000 0x40024000 0x40024000 0x00000 0x0000c RW  0x10000
  
   Section to Segment mapping:
    Segment Sections...
     00     .isr_vector .firmware_header_vector .text .exidx .init_array .fini_array 
     01     .data_x 
     02     .firmware_header 
     03     .eth .bss 
     04     .battery_backed_sram 
  </code></pre>
  
  <p>How does objcopy know not to insert sections such as .bss in to the output image? I know that it computes this on the fly, and I'm assuming this mechanism is driven through the section to segment mapping, but I cannot find any explanation as to how it <em>actually</em> performs the segment to section mapping. The elf file stores no information about which segments are flash, and yet somehow objcopy knows that it should not copy .bss into the output file. How?</p>