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.

CCS/AM3352: CCS 7.1 debugger attempts to load an AM3352 bootloader compiled with the GCC ARM compiler to an incorrect memory address

Part Number: AM3352
Other Parts Discussed in Thread: AM3359

Tool/software: Code Composer Studio

Was using CCS 7.1.0.00016 running under Ubuntu 16.04 LTS to attempt to debug a bootloader on the Cortex-A8 of an AM3352, where the bootloader should be loaded and run in the "SRAM internal" region from 0x402F0400 .. 0x402FFFFF. The bootloader is compiled using the gcc-arm-none-eabi-4_9-2015q3 compiler.

When attempting to load the program the load fails with the following error reported in the console:

CortxA8: Output: ****  AM3352_SOM Initialization is in progress .......... 
CortxA8: Output: ****  AM335x ALL PLL Config for OPP == Turbo is in progress ......... 
CortxA8: Output: Input Clock Read from SYSBOOT[15:14]:  24MHz
CortxA8: Output: ****  Going to Bypass... 
CortxA8: Output: ****  Bypassed, changing values... 
CortxA8: Output: ****  Locking ARM PLL
CortxA8: Output: ****  Core Bypassed
CortxA8: Output: ****  Now locking Core...
CortxA8: Output: ****  Core locked
CortxA8: Output: ****  PER DPLL Bypassed
CortxA8: Output: ****  PER DPLL Locked
CortxA8: Output:  ****  AM335x ALL PLL Config for OPP == Turbo is done ......... 
CortxA8: Output: ****  AM3352_SOM Initialization is Done ****************** 


CortxA8: Trouble Writing Memory Block at 0x402f0074 on Page 0 of Length 0x7ff0: (Error -1065 @ 0x3D5A) Unable to access device memory. Verify that the memory address is in valid memory. If error persists, confirm configuration, power-cycle board, and/or try more reliable JTAG settings (e.g. lower TCLK). (Emulation package 6.0.628.1) 
CortxA8: File Loader: Verification failed: Target failed to write 0x402F0074
CortxA8: GEL: File: /home/mr_halfword/AM3352-SOM-EVB_bare_metal/Debug/bootloader/bootloader.out: Load failed.

The debugger reports that is attempt to write a memory block of size 0x7ff0 bytes starting at address 0x402f0074. However, that starting address and size doesn't match the sections in the program. Running the cg_xml sectti utility on the bootloader ELF file confirms that the starting load address is 0x402f0400 as expected:

~/ti/cg_xml/utils/ofd6x -x bootloader/bootloader.out | ~/ti/cg_xml/bin/sectti 
Reading from stdin ...

************************************************************
REPORT FOR FILE: bootloader/bootloader.out
************************************************************
                Name : Size (dec)  Size (hex)  Type   Load Addr   Run Addr
-------------------- : ----------  ----------  ----   ----------  ----------
            .rsthand :         32  0x00000020  CODE   0x402f0400  0x402f0400
               .text :      35168  0x00008960  CODE   0x402f0420  0x402f0420
               .data :       1084  0x0000043c  DATA   0x402f8d88  0x402f8d88
                .bss :       2184  0x00000888  UDATA  0x402f9200  0x402f9200
              .stack :       8192  0x00002000  UDATA  0x402f9a90  0x402f9a90

------------------------------------------------------------
Totals by section type
------------------------------------------------------------
  Uninitialized Data :      10376  0x00002888
    Initialized Data :       1084  0x0000043c
                Code :      35200  0x00008980

Attached is the debug server log file from a failure to load. 4645.debug_server.log.zip

Searching the debug server log for the incorrect load address 0x402f0074 shows it first appears in the part of the log which is about parsing the ELF information for the program to be loaded:

0x7FD3469FB700 320382 4  OFS I: PT_LOAD: 
0x7FD3469FB700 320382 4  OFS D: OFS LOAD Section added:  name: .text
0x7FD3469FB700 320382 4  OFS D:   size in bytes: 37200, or 0x9150
0x7FD3469FB700 320382 4  OFS D:   load location: 0x402f0074
0x7FD3469FB700 320382 4  OFS D:   run location: 0x402f0074
0x7FD3469FB700 320382 4  OFS D:   memory page: 0
0x7FD3469FB700 320382 4  OFS D:   offset in file: 116 or 0x74
0x7FD3469FB700 320382 4  OFS D: OFS LOAD Section added:  name: padding
0x7FD3469FB700 320382 4  OFS D:   size in bytes: 10444, or 0x28cc
0x7FD3469FB700 320382 4  OFS D:   load location: 0x402f91c4
0x7FD3469FB700 320382 4  OFS D:   run location: 0x402f91c4
0x7FD3469FB700 320382 4  OFS D:   memory page: 0
0x7FD3469FB700 320382 4  OFS D:   offset in file: 0 or 0x0

Therefore, think the problem is that the CCS 7.1 debugger is incorrectly reading the address of the sections to load from the bootloader.out ELF file. The build directory containing the bootloader.out file is attached. bootloader.zip

https://github.com/Chester-Gillon/AM3352-SOM-EVB_bare_metal/blob/b99ab552f96f4cab27094f9e5937e012725eee90/bootloader/targetConfigs/AM3352.ccxml is the target configuration file which was used when attempt to debug the bootloader.out. The target configuration uses custom GEL files on the Cortex-A8 and ICEpick_D, where the GEL files are in https://github.com/Chester-Gillon/AM3352-SOM-EVB_bare_metal/tree/b99ab552f96f4cab27094f9e5937e012725eee90/gel_files directory.

  • Chester Gillon said:
    Was using CCS 7.1.0.00016 running under Ubuntu 16.04 LTS to attempt to debug a bootloader on the Cortex-A8 of an AM3352, where the bootloader should be loaded and run in the "SRAM internal" region from 0x402F0400 .. 0x402FFFFF. The bootloader is compiled using the gcc-arm-none-eabi-4_9-2015q3 compiler.

    The project started off as being compiled using CCS project files and the TI ARM v5.2.6 compiler. At some point the project was changed to use CMake to generate the makefiles and use the GCC ARM compiler.

    I reverted the project to being compiled using the TI ARM v5.2.6 compiler and CCS 7.1.0.00016 running under Ubuntu 16.04 LTS was then able to successfully download and debug the bootloader.out ELF file.

    The bootloader compiled by the gcc-arm-none-eabi-4_9-2015q3 compiler is a valid program, since if the generated binary MLO file is copied to a SD card the bootloader is successfully run by the AM3352 boot ROM. The problem is that the ELF bootloader.out file generated by the gcc-arm-none-eabi-4_9-2015q3 compiler can not be successfully downloaded into RAM by the CCS 7.1.0.00016 debugger.

    The same target hardware, Blackhawk USB560-M Emulator, target configuration file and GEL files were used for the successfully download of the TI ARM compiler generated program and un-successful download of the GCC ARM compiler generated program.

  • I am able to reproduce this on an AM3359 BeagleBone. We will need to dig into the symbol info to figure out why CCS things the load address is 0X402F0074.
  • JohnS said:
    I am able to reproduce this on an AM3359 BeagleBone. We will need to dig into the symbol info to figure out why CCS things the load address is 0X402F0074.

    I was using the Ubuntu readelf utility to look at the headers for the bootloader.out file generated by the GCC ARM compiler for which CCS attempts to start writing to memory at the address 0x402F0074:

    $ readelf -hlS bootloader/bootloader.out 
    ELF Header:
      Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
      Class:                             ELF32
      Data:                              2's complement, little endian
      Version:                           1 (current)
      OS/ABI:                            UNIX - System V
      ABI Version:                       0
      Type:                              EXEC (Executable file)
      Machine:                           ARM
      Version:                           0x1
      Entry point address:               0x402f0400
      Start of program headers:          52 (bytes into file)
      Start of section headers:          97760 (bytes into file)
      Flags:                             0x5000402, Version5 EABI, hard-float ABI, <unknown>
      Size of this header:               52 (bytes)
      Size of program headers:           32 (bytes)
      Number of program headers:         2
      Size of section headers:           40 (bytes)
      Number of section headers:         21
      Section header string table index: 18
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .rsthand          PROGBITS        402f0400 000400 000020 00  AX  0   0  4
      [ 2] .text             PROGBITS        402f0420 000420 008960 00  AX  0   0  8
      [ 3] .ARM.exidx        ARM_EXIDX       402f8d80 008d80 000008 00  AL  2   0  4
      [ 4] .data             PROGBITS        402f8d88 008d88 00043c 00  WA  0   0  8
      [ 5] .bss              NOBITS          402f9200 0091c4 000888 00  WA  0   0 128
      [ 6] .heap             PROGBITS        402f9a90 0091d0 000000 00      0   0 16
      [ 7] .stack            NOBITS          402f9a90 0091c4 002000 00   A  0   0 16
      [ 8] .ARM.attributes   ARM_ATTRIBUTES  00000000 0091d0 00002f 00      0   0  1
      [ 9] .comment          PROGBITS        00000000 0091ff 000070 01  MS  0   0  1
      [10] .isr_vector       PROGBITS        00000000 009270 000050 00      0   0 16
      [11] .debug_info       PROGBITS        00000000 0092c0 0059df 00      0   0  1
      [12] .debug_abbrev     PROGBITS        00000000 00ec9f 0010c2 00      0   0  1
      [13] .debug_aranges    PROGBITS        00000000 00fd61 0008a8 00      0   0  1
      [14] .debug_ranges     PROGBITS        00000000 010609 0007a8 00      0   0  1
      [15] .debug_line       PROGBITS        00000000 010db1 002e60 00      0   0  1
      [16] .debug_str        PROGBITS        00000000 013c11 002115 01  MS  0   0  1
      [17] .debug_frame      PROGBITS        00000000 015d28 001fe8 00      0   0  4
      [18] .shstrtab         STRTAB          00000000 017d10 0000cd 00      0   0  1
      [19] .symtab           SYMTAB          00000000 018128 002280 10     20 363  4
      [20] .strtab           STRTAB          00000000 01a3a8 0013d8 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings)
      I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
      O (extra OS processing required) o (OS specific), p (processor specific)
    
    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      EXIDX          0x008d80 0x402f8d80 0x402f8d80 0x00008 0x00008 R   0x4
      LOAD           0x000000 0x402f0000 0x402f0000 0x091c4 0x0ba90 RWE 0x8000
    
     Section to Segment mapping:
      Segment Sections...
       00     .ARM.exidx 
       01     .rsthand .text .ARM.exidx .data .bss .stack 

    The alignment for the LOAD Program Header is set to 0x8000 (32 Kbytes) and the the least 15 bits of the ELF file offset for the sections to load match the least significant 15 bits of the load address. I think this is an optimization which allows the ELF loader (the CCS debugger in this case) to attempt to write a consecutive array of bytes from the ELF file straight to program memory. The ELF file starts with a 52 byte header and two program headers of 32 bytes which is a total of 52 + (2 * 32) = 116 = 0x74 which matches the least significant 15 bits of the address 0x402F0074 which the CCS debugger attempts to write to. Since on a AM3352 the address range 0x402F0000 .. 0x402F03FF is reserved and can't be written, that explains why the "alignment optimization" for the load of the program into memory fails.

    The GCC linker was changed to reduce the alignment for the LOAD Program Header from the default 0x8000 down to 0x400 bytes, by adding the option "-z max-page-size=0x400". With that change the CCS 7.1 debugger could successfully load the bootloader.out file into memory. The addition of the max-page-size option didn't change the generated binary MLO file, only the LOAD Program Header in the ELF file which was preventing the CCS debugger from loading the bootloader.out file into memory.

    Not sure if the loader in the CCS debugger which decides how the load the contents of the ELF file into memory should be immune to the condition where the LOAD Program Header alignment causes an attempt to memory which isn't accessible.

  • For ELF output, all debuggers (not just CCS debugger) always use the ELF program header to load the segments to the target.

    This is not an optimization employed by the debugger. This is defined in the ELF specification.

    If the linker gives out invalid segment table, we will write to the wrong addresses.

    In this case, the program header specifies

    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      EXIDX          0x008d80 0x402f8d80 0x402f8d80 0x00008 0x00008 R   0x4
      LOAD           0x000000 0x402f0000 0x402f0000 0x091c4 0x0ba90 RWE 0x8000

    We load the loadable segment to 0x402f000 from file offset 0 with filesize 0x91c4 and memsize 0xba90.

    CCS will never write the ELF header (located at file offset 0x0) to memory so CCS adds the size of the ELF headers to the file offset and load address.

    Therefore, we write to the memory address 0x402f0074  (0x91c4-0x74) bytes of data starting from file offset 0x74.

    Since the memory size of this segment is larger than the file size of the segment, we zero-fill the memory region from 0x402f91c4 to 0x402fba90.

    As far as I can see, we are doing what is specified in the ELF header.

    I do not think that this is a CCS bug.

    This looks like a gcc linker bug or linker usage issues.

    Regards,

    Raymond  

  • Raymond Pang said:
    For ELF output, all debuggers (not just CCS debugger) always use the ELF program header to load the segments to the target.

    This is not an optimization employed by the debugger. This is defined in the ELF specification.

    Thank you the the clarification of how the ELF program header is used. I confirm that the debugger in the IAR Embedded Workbench for ARM behaves in the same way as the CCS debugger in how the ELF program header is used to load the segments to the target.

    Raymond Pang said:
    This looks like a gcc linker bug or linker usage issues.

    The gcc-arm-none-eabi-4_9-2015q3 linker supplied with CCS 7.1 has a default max-page-size of 0x8000, and when looked at some example SYS/BIOS programs for Cortex-M and Cortex-A targets nothing in the example linker scripts was overriding the default max-page-size.

    Now that understand the GCC ARM linker behaviour simply have to set the max-page-size linker option for any programs which require writing to memory regions where the start address or size are not aligned to the default max-page-size of 32 Kbytes.