EmbDev.net

Forum: ARM programming with GCC/GNU tools Data Access Abort exception during sprintf execution with fp


von roty (Guest)


Rate this post
useful
not useful
Hello,

I'm getting a Data Access Abort exception during program execution in
a sprintf function, if floating-point format keys are used. The
postings regarding similar issues in this forum and some other do not
really help me.

I'm new with GNUARM and I eventually got all stuff working so far. But
the mentioned issue knocks me out, so I need new ideas what could be
wrong.

I'm using GNUARM version 4.1.0. The compiler delivers no error or
warning. Also the parameters of the sprintf function should be ok.
Another C-Compiler and its library has also no problems!

I found the location of the asm instruction in the lib area which
causes the issue.
str r0,[r10,#0x4] but r10 contains 0xC0.
Other sprintf calls with non fp format keys work also perfect.

Could there something be wrong with the library ? Could I use a wrong
library ?

Any further idea ?

Thanks for any help.

von Clifford S. (clifford)


Rate this post
useful
not useful
The printf family of functions require a relatively large ammount of
stack, and probably more so for floating point specifiers. Are you sure
you have sufficient stack allocated?

Also just because code does not crash with one compiler/platform and
does on another does not mean that that it is valid, it may just mean
that the memory mapping of the other was such that the error did not
cause a data abort (which happens when you access unmapped memory or
memory without appropriate access attributes).

You should post the code, and also your compile log. Are you sure that
your sprintf buffer is large enough to take the generated string?

Clifford

von roty (Guest)


Rate this post
useful
not useful
Thanks for your answer. I appreciate any wise idea.

Clifford Slocombe wrote:
> The printf family of functions require a relatively large ammount of
> stack, and probably more so for floating point specifiers. Are you sure
> you have sufficient stack allocated?
>

Yes, I think so. I already found some similar hints in different forums
and I
took care useing a really unusual hugh amount of stack area.

> Also just because code does not crash with one compiler/platform and
> does on another does not mean that that it is valid, it may just mean
> that the memory mapping of the other was such that the error did not
> cause a data abort (which happens when you access unmapped memory or
> memory without appropriate access attributes).
>

I agree, however, if the result is excatly what's expected, then one
must
assume that there is no issue! Memory map is subjectivly the same in
both
cases, due to CPU recources.

> You should post the code, and also your compile log. Are you sure that
> your sprintf buffer is large enough to take the generated string?

I have a code snippet extracted which allows to duplicate the issue. All
stuff
around is 1MByte including makefile, etc. (Eclipse project). How can I
post it here ?

Thanks

von Clifford S. (clifford)


Rate this post
useful
not useful
roty wrote:
> I agree, however, if the result is excatly what's expected, then one
> must
> assume that there is no issue! Memory map is subjectivly the same in
> both
> cases, due to CPU recources.
>

I am not sure your argument holds. Experience shows that even adding an
unrelated piece of code or changing a compiler option can change an
apparently working piece of code to non-working and vice versa. By thier
nature memory errors (buffer overruns, invalid pointers, stack
corruption etc.) have non deterministic results.

>
> I have a code snippet extracted which allows to duplicate the issue. All
> stuff
> around is 1MByte including makefile, etc. (Eclipse project). How can I
> post it here ?
>
Initilaly at least it should not be necessary to post all project
related files (and that is not what I asked for). It does not take 1Mb
of information to provide an example of how you are calling sprintf().
Just the code fragment. It may not help, and you may believe that it
will not help, but you have to understand that we are not with you,
seeing what you are seeing; so we don't have the benefit of all the
information available to you, regardless of how irrelevant you may think
it is. It is a simple request that may simply give us confidence in what
you are telling us - as we would have if we were say next to you.
Remote/blind debugging is difficult, and success is all about quality of
information. Hence the request for code and build log - that way we see
what you are compiling and how you are compiling it. Experience on other
forums has proven to me that that is the fastest way to solve problems.
Since it is you who have the problem it is not really for you to second
guess those that may help you by arguing about what information you nedd
or need not supply.

For exampel, you only mentioned the exact instruction the abort occurs
in, but that does not really help at all in isolation, what is more
helpful is how it got there - a function call stack dump would be far
more helpful. You have not been clear whether the error occurs withing
the sprintf call or simply withing your program when th esprintf call is
present. This is critical to charactarising the nature of your problem -
and teh kind of questions I'd be asking myself if I were there.



Clifford

von Martin Thomas (Guest)


Rate this post
useful
not useful
roty wrote:
> Thanks for your answer. I appreciate any wise idea.
>
> Clifford Slocombe wrote:
>> The printf family of functions require a relatively large ammount of
>> stack, and probably more so for floating point specifiers. Are you sure
>> you have sufficient stack allocated?
>
> Yes, I think so. I already found some similar hints in different forums
> and I took care useing a really unusual hugh amount of stack area.

I once had a problem when using stdio-functions which has been caused by
a to small stack. I share Clifford's opinion that it's probably a
stack/memory-issue. Since the stdio-functions use the heap too there
might also be a memory-mismatch or some overlapping. You might check the
linker-script (placement of the "end"-symbol) and the sbrk-syscall
again. The newlib's (s)printf functions work with floating-point-format
here. But I use my WinARM-collection not the GNUARM-collection. Maybe
the newlib in the GNUARM-collection is compiled without floating-point
support. But I expect this will be answered in your crosspost in the
GNUARM yahoo-group. I expect the GNUARM-maintainer has build with
FP-support.

Since you can locate the assembler instruction which seems to cause the
data-abort exception I expect you have a JTAG-interface available. Try
to monitor the stack-pointer and set a breakpoint in sbrk with a
debugger.

Verify that you are increasing the size of the used stack. There is
example-code out there which is executed in supervisor mode and other
code which is executed in user-mode. Maybe you have increase a the size
of a stack which is not used for the "normal" execution.

Another shoot in the dark: Verify that -lm is passed to the
compiler-frontend when linking.

>> ...
>...

>> You should post the code, and also your compile log. Are you sure that
>> your sprintf buffer is large enough to take the generated string?
>
> I have a code snippet extracted which allows to duplicate the issue. All
> stuff around is 1MByte including makefile, etc. (Eclipse project). How can I
> post it here ?

Uff - 1MByte - this is not an "extracted snippet", please try to create
an minimal example without any Eclipse files and files created during
the build process (o, elf, map, sym etc.). Just the sources (C and
assembler-startup), linker-script and a makefile and a text-file with
the redirected output of a make all after a make clean. Not more than
some kBytes needed for this. Pack everything together (zip prefered) and
send it as e-mail attachment to mthomas(at)rhrk(dot)uni-kl(dot)de and I
will place it on the "WinARM"-webserver and send the link here.

Martin Thomas

von Stefan (Guest)


Rate this post
useful
not useful
roty, you are a little bit extreme... either 1 assembler line or 1 MB.
Choose the right mixture! I'll give you an example:

Sample code:
============
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
  char line[128];
  sprintf(line, "     %#5.3f     ", 3.2);
  while(1);
  return 0;  // never reached!
}

Additional infos:
- Include files are from GNUARM 4.1.0 installation.
- #define _NEWLIB_VERSION "1.14.0" in newlib.h

Commandlines of 'make all':
===========================
> "make.exe" all

-------- begin --------
arm-elf-gcc (GCC) 4.1.0
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.


Assembling: startup.S
arm-elf-gcc -c -mcpu=arm7tdmi -I. -x assembler-with-cpp -DROM_RUN
-Wa,-adhlns=startup.lst,-gstabs startup.S -o startup.o

Compiling: main.c
arm-elf-gcc -c -mcpu=arm7tdmi -I. -gstabs -DROM_RUN  -O0 -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -MD -MP -MF
.dep/main.o.d main.c -o main.o

Linking: main.elf
arm-elf-gcc -mcpu=arm7tdmi -I. -gstabs -DROM_RUN  -O0 -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=startup.o  -std=gnu99 -MD -MP -MF
.dep/main.elf.d startup.o main.o --output main.elf -nostartfiles
-Wl,-Map=main.map,--cref -lc  -lm -lc -lgcc -TAT91R40008-NavMe-ROM.ld

Creating load file for Flash: main.hex
arm-elf-objcopy -O binary main.elf main.hex

Creating Extended Listing: main.lss
arm-elf-objdump -h -S main.elf > main.lss

Creating Symbol Table: main.sym
arm-elf-nm -n main.elf > main.sym

Size after:
main.elf  :
section             size       addr
.text              34164   16777216
.data               2084          0
.bss                 244       2084
.stack              1024       2560
.stab               2412          0
.stabstr            6112          0
.comment             720          0
.debug_aranges      1408          0
.debug_pubnames     2524          0
.debug_info        91565          0
.debug_abbrev      16083          0
.debug_line        16296          0
.debug_frame        3592          0
.debug_str          6675          0
.debug_loc         31946          0
.debug_ranges       1232          0
Total             218081



Errors: none
-------- end --------


> Process Exit Code: 0
> Time Taken: 00:20

Additional infos from lines above:
- target is arm7tdmi (in detail AT91R40008)
- i compiled for ROM with own Startup.S file and own linker control
scripts
  (maybe in a real bugfix case someone wants to see these files, be
prepared)
- i used standard libc, libgcc and libm libraries

The project was compiled with this makefile:
============================================
# Hey Emacs, this is a -*- makefile -*-
#
# GNUARM template makefile
# based on WinARM template makefile

# based on the WinAVR makefile written by Eric B. Weddington, Jörg
Wunsch, et al.
# Released to the Public Domain
# Please read the make user manual!
#
#
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make program = Download the hex file to the device, using isp21lpc
#
# make filename.s = Just compile filename.c into the assembler code only
#
# To rebuild project do "make clean" then "make all".
#
# v0.1  Stefan  1st version for GNUARM & AT91R40008 on NavMe board
#

# MCU name and submodel
MCU = arm7tdmi
SUBMDL = AT91R40008-NavMe


## Create ROM-Image (final)
RUN_MODE=ROM_RUN
## Create RAM-Image (debugging)
#RUN_MODE=RAM_RUN


# Output format. (can be srec, ihex, binary)
# FORMAT = ihex
FORMAT = binary


# Target file name (without extension).
TARGET = main


# List C source files here. (C dependencies are automatically
generated.)
SRC = $(TARGET).c


# List Assembler source files here.
# Make them always end in a capital .S.  Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
#ASRC = crt0.S
ASRC = startup.S


# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = 0

# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
#DEBUG = dwarf-2
DEBUG = stabs

# List any extra directories to look for include files here.
#     Each directory must be seperated by a space.
#EXTRAINCDIRS = ./include
EXTRAINCDIRS =

# Compiler flag to set the C Standard level.
# c89   - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99   - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99

# Place -D or -U options for C here
CDEFS =  -D$(RUN_MODE)

# Place -I options here
CINCS =

# Place -D or -U options for ASM here
ADEFS =  -D$(RUN_MODE)


# Compiler flags.
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct
-fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)


# Assembler flags.
#  -Wa,...:   tell GCC to pass this to the assembler.
#  -ahlms:    create listing
#  -gstabs:   have the assembler create line number information; note
that
#             for use in COFF files, additional information about
filenames
#             and function names needs to be present in the assembler
source
#             files -- see avr-libc docs [FIXME: not yet described
there]
##ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:.S=.lst),-g$(DEBUG)

#Additional libraries.

#Support for newlibc-lpc (file: libnewlibc-lpc.a)
#NEWLIBLPC = -lnewlib-lpc
NEWLIBCLPC =

MATH_LIB = -lm

# Linker flags.
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += -lc
LDFLAGS += $(NEWLIBLPC) $(MATH_LIB)
LDFLAGS += -lc -lgcc

# Set Linker-Script Depending On Selected Memory
ifeq ($(RUN_MODE),RAM_RUN)
LDFLAGS +=-T$(SUBMDL)-RAM.ld
else
LDFLAGS +=-T$(SUBMDL)-ROM.ld
endif



#
------------------------------------------------------------------------ 
---
# Flash-Programming support using lpc21isp by Martin Maurer

# Settings and variables:
#LPC21ISP = lpc21isp
#LPC21ISP_PORT = com1
#LPC21ISP_BAUD = 115200
#LPC21ISP_XTAL = 14746
#LPC21ISP_FLASHFILE = $(TARGET).hex
# verbose output:
## LPC21ISP_DEBUG = -debug
# enter bootloader via RS232 DTR/RTS (only if hardware supports this
# feature - see Philips AppNote):
## LPC21ISP_CONTROL = -control


#
------------------------------------------------------------------------ 
---

# Define directories, if needed.
## DIRARM = c:/WinARM/
## DIRARMBIN = $(DIRAVR)/bin/
## DIRAVRUTILS = $(DIRAVR)/utils/bin/

# Define programs and commands.
SHELL = sh
CC = arm-elf-gcc
OBJCOPY = arm-elf-objcopy
OBJDUMP = arm-elf-objdump
SIZE = arm-elf-size
NM = arm-elf-nm
REMOVE = rm -f
COPY = cp


# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = --------  end  --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_FLASH = Creating load file for Flash:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_LPC21_RESETREMINDER = You may have to bring the target in
bootloader-mode now.


# Define all object files.
OBJ = $(ASRC:.S=.o) $(SRC:.c=.o)


# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)


# Compiler flags to generate dependency files.
### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d

# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mcpu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mcpu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)


# Default target.
all: begin gccversion sizebefore build sizeafter cpbinary finished end

build: elf hex lss sym

elf: $(TARGET).elf
hex: $(TARGET).hex
lss: $(TARGET).lss
sym: $(TARGET).sym

# Eye candy.
begin:
  @echo
  @echo $(MSG_BEGIN)

cpbinary:
  @if ! [ -d $(RUN_MODE) ]; then mkdir $(RUN_MODE) ; fi
  @cp $(TARGET).hex $(RUN_MODE)/$(TARGET).bin
  @cp $(TARGET).lss $(RUN_MODE)/
  @cp $(TARGET).elf $(RUN_MODE)/

finished:
  @echo $(MSG_ERRORS_NONE)

end:
  @echo $(MSG_END)
  @echo


# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
sizebefore:
  @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE);
$(ELFSIZE); echo; fi

sizeafter:
  @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER);
$(ELFSIZE); echo; fi


# Display compiler version information.
gccversion :
  @$(CC) --version


# Program the device.
program: $(TARGET).hex
  @echo Make Program ist noch nicht möglich
#   @echo $(MSG_LPC21_RESETREMINDER)
# @echo $(LPC21ISP) $(LPC21ISP_CONTROL) $(LPC21ISP_DEBUG)
$(LPC21ISP_FLASHFILE) $(LPC21ISP_PORT) $(LPC21ISP_BAUD) $(LPC21ISP_XTAL)


# Create final output files (.hex, .eep) from ELF output file.
# TODO: handling the .eeprom-section should be redundant
%.hex: %.elf
  @echo
  @echo $(MSG_FLASH) $@
  $(OBJCOPY) -O $(FORMAT) $< $@


# Create extended listing file from ELF output file.
%.lss: %.elf
  @echo
  @echo $(MSG_EXTENDED_LISTING) $@
  $(OBJDUMP) -h -S $< > $@


# Create a symbol table from ELF output file.
%.sym: %.elf
  @echo
  @echo $(MSG_SYMBOL_TABLE) $@
  $(NM) -n $< > $@


# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
  @echo
  @echo $(MSG_LINKING) $@
  $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)


# Compile: create object files from C source files.
%.o : %.c
  @echo
  @echo $(MSG_COMPILING) $<
  $(CC) -c $(ALL_CFLAGS) $< -o $@


# Compile: create assembler files from C source files.
%.s : %.c
  $(CC) -S $(ALL_CFLAGS) $< -o $@


# Assemble: create object files from assembler source files.
%.o : %.S
  @echo
  @echo $(MSG_ASSEMBLING) $<
  $(CC) -c $(ALL_ASFLAGS) $< -o $@


# Target: clean project.
clean: begin clean_list finished end


clean_list :
  @echo
  @echo $(MSG_CLEANING)
  $(REMOVE) $(TARGET).hex
  $(REMOVE) $(TARGET).obj
  $(REMOVE) $(TARGET).elf
  $(REMOVE) $(TARGET).map
  $(REMOVE) $(TARGET).obj
  $(REMOVE) $(TARGET).a90
  $(REMOVE) $(TARGET).sym
  $(REMOVE) $(TARGET).lnk
  $(REMOVE) $(TARGET).lss
  $(REMOVE) $(OBJ)
  $(REMOVE) $(LST)
  $(REMOVE) $(SRC:.c=.s)
  $(REMOVE) $(SRC:.c=.d)
  $(REMOVE) .dep/*


# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)


# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex lss sym \
clean clean_list program

Additional infos:
- i changed:
  MCU = arm7tdmi
  SUBMDL = AT91R40008-NavMe
  RUN_MODE=ROM_RUN
  ASRC = startup.S
  and i think the debug format

BTW. I extracted sprintf.o from my libc.a library with ar and
disassembled sprintf.o with objdump. I couldn't find the assembler line
you gave us.

Since it is a run-time error, it would surely help to disassemble a
region surrounding the bug in GDB. And you should include a partial dump
of stack frames too.

Stefan

von roty (Guest)


Rate this post
useful
not useful
I'm feeling totally misinterpreted!

But I'll will not justify myself, I just want to get the issue fixed.

Thomas got all he requested, thanks.

von roty (Guest)


Rate this post
useful
not useful
Sri

Martin got all he requested, danke.

von Stefan (Guest)


Rate this post
useful
not useful
roty wrote:
> I'm feeling totally misinterpreted!

Which kind of misinterpretation?

Some people really want to help you, because (or but) they are asking
for more details.

It is your "single task" to give answers and all information which is
required to reproduce the error on another machine and to give a
detailed description of the error situation on your machine.

Keep in mind, that others use another development environment and you
should describe your development environment as good as possible. This
is which µC, which toolchain, which libraries. All this will help others
in their attempt to reproduce the error and - we hope - eventually find
a solution.

Some of us read each and every snippet of µC information available in
different forums. But not all do. References to some of your questions
in other forums and some answers given here and there don't help, when
you don't give links to these discussions.

OK back to my last answer. I tried to show you how such information may
look like. I don't use Eclipse but Programmers Notepad 2 with GNUARM.
Keep in mind, that when you insist on your mega-Eclipse-project then the
number of answers may be limited to come from other Eclipse programmers
only.

My simple snippet of source code is to prove the correctness or fault of
sprintf with your arguments. The call sequence for the toolchain with
actual compile log and the actual makefile help to reproduce the compile
process. You can (and should) add debug log information, too.

Does this kind of code compile and run OK on your system? Then it may be
a runtime effect (e.g. stack or pointer or buffer or initialization
problems) in your program instead of a broken sprintf implementation.

Stefan

von Martin Thomas (Guest)


Rate this post
useful
not useful
OK.

I share Stefan's option in most points. I'd like to suggest to read Eric
Raymont's "How to ask questions...". But back to business.

I have stripped down rty's 1MByte package to what I think is needed for
others. It is available  in
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/winarmtests
as file rty_sprintf_problem_and_suggestion.zip.

There are two directories in the package: rty_incoming is the code that
has been sent by rty but I have deleted the eclipse-files and the
output-files.

Well, I have ported the code so it can be compiled with the tools and
setup as in WinARM and used my Makefile-template, also hacked around in
the linker-script, source and startup a little bit. My modification is
available in the directory rty_modified_mthomas in the zip-archive in
case anybody is interested.

I think that I have found the reason for the issue (only verified with a
simulator): Since the stdio-functions use the heap and it seems that
when floating-points are involved a rather large portion of heap gets
used temporarily a working heap-management is needed (basicly the
end-symbol and sbrk, the rest is done by the newlib-functions). The
problem seemes to be a rather subtile "double-declaration": in the
startup-code there is an end-label used after the "branch to main()".
The line is "end: b end". But this symbol is also used by the
heap-managmend syscall (either in the orignal newlib-code as used in the
rty-code or in the syscall.c I have used). So the "label" overwrites the
end-symbol defined in the linker and the heap-allocation did work with a
wrong label. I hacked around at various places but finaly when I
replaced the "end" in the startup by a differend label and it seems to
work.

Martin Thomas

(Uff, I think I have to review a lot of my WinARM examples to see if the
issue is present in some of the examples too).

von Stefan (Guest)


Rate this post
useful
not useful
Nasty! And nice work to spot the bug.

I use a Startup.S which has another code for the main() call and handler
for a return from main() call.

The duplicate 'end' symbol is not here, but some other global labels
like _reset, reset, exit, abort.

BTW. i think the implementation of these functions is not good in this
code. Reset should be a real reset and not a loop forever. Comments?

// ############################################################
  .global main                    // int main(void)
  ldr r0, =main      // __main
  bx r0

  .size   _start, . - _start
  .endfunc

//
// The function main() should be a closed loop and should not return.
//
      .global _reset, reset, exit, abort
      .func   _reset
_reset:
reset:
exit:
abort:
      b     .                         // loop until reset

      .size _reset, . - _reset
  .endfunc
// ############################################################

Stefan

von roty (Guest)


Rate this post
useful
not useful
Martin got it !

After deleting the end symbol and entering his "provide end" line in the
linker
script, the problem disappeared evntually.

Btw, it was not my own idea to enter the end symbol that way. I got a
hint right
in this forum some days ago, as I asked for a solution regrading an
undefined
reference to `end' . Maybe I understood something wrong.

Anyway, thank you to all who wasted their time to help me to fix it
finally..

As a GCC novice ,  I would never be able to find such an issue .

I'll also take all your comments , suggestions and complains regarding
how to ask
questions into account next time.

Thanks again.

von Stefan (Guest)


Rate this post
useful
not useful
Maybe i gave you the hint with end as global symbol in startup code,
because you had a problem with a missing global symbol end before. I am
sorry and i hope you can forgive me.

Stefan

von Clifford S. (clifford)


Rate this post
useful
not useful
Stefan wrote:
> BTW. i think the implementation of these functions is not good in this
> code. Reset should be a real reset and not a loop forever. Comments?
>

A suggestion:
//------------------------------
_reset:
reset:
exit:
#if defined NDEBUG
abort:
#endif
    //-----------------------------------------
    // Enable the uC's watchdog for reset here
    //-----------------------------------------
      b     .                         // loop until reset

#if !defined NDEBUG
abort:
    //-----------------------------------------
    // Disable the uC's watchdog here
    //-----------------------------------------
#endif
      b     .                         // loop until reset

      .size _reset, . - _reset
  .endfunc
//------------------------------

The a hardware reset will occur after a jump to reset or exit, and if
not a debug build abort also. If it is a debug build, the abort still
loops indefinitely allowing a debugger to be attatched for port-mortem.

Unfortunatly the solution is target hardware specific.

Clifford

von Stefan (Guest)


Rate this post
useful
not useful
@ Martin

the idea to call a user function or variable 'end' in the user program
code is not so far away. In both cases the toolchain gives no
error/warning.

Maybe the library/linker control script should use a name beginning with
an underscore like other global symbols that are implemented by compiler
and/or in library?

When you look for docs about end/_end you'll find docs with _end as name
for this global symbol. Here are some samples:

See http://sca.uwaterloo.ca/coldfire/gcc-doc/docs/porting_3.html
"The linker script sets up the memory map of an application. It also
sets up default values for variables used elsewhere by sbrk() and the
crt0. These default variables are typically called _bss_start and _end."

And
https://www.redhat.com/docs/manuals/gnupro/GNUPro-Toolkit-02r1/gsIX.html
"Symbols
#define 21
#include files 21, 120, 129
.bss 39- 40, 42
.data 42
.text 40
.text section 41
__start 37
_bss_start 40, 42
_DYNAMIC, for shared dynamic libraries 41
_end 40, 42"

And http://www.davehylands.com/avi/linker_scripts.htm in combination
with http://www.davehylands.com/avi/downloads/libmrm/sbrk.c

And ChangeLog entry 2005-10-28 of newlib 1.14.0

BUT before i introduce a new nasty bug - there is already a symbol _end
as you can see with the nm tool.

Some (!) other systems (see sbrk.[cs] or syscalls.c files in sys/*
folders) use something like sbrk_end or _end_heap globals. Most
architectures other than arm use 'end' too.

Stefan

von Stefan (Guest)


Rate this post
useful
not useful
Clifford, i like your idea with the reset with watchdog and different
#define sections for DEBUG or NDEBUG sessions.

Stefan

von Martin Thomas (Guest)


Rate this post
useful
not useful
Stefan wrote:
> @ Martin
>
> the idea to call a user function or variable 'end' in the user program
> code is not so far away. In both cases the toolchain gives no
> error/warning.
>
> Maybe the library/linker control script should use a name beginning with
> an underscore like other global symbols that are implemented by compiler
> and/or in library?
>
> When you look for docs about end/_end you'll find docs with _end as name
> for this global symbol. Here are some samples:
>
> See http://sca.uwaterloo.ca/coldfire/gcc-doc/docs/porting_3.html
> "The linker script sets up the memory map of an application. It also
> sets up default values for variables used elsewhere by sbrk() and the
> crt0. These default variables are typically called _bss_start and _end."
>
> And
> https://www.redhat.com/docs/manuals/gnupro/GNUPro-Toolkit-02r1/gsIX.html
> "Symbols
> #define 21
> #include files 21, 120, 129
> .bss 39- 40, 42
> .data 42
> .text 40
> .text section 41
> __start 37
> _bss_start 40, 42
> _DYNAMIC, for shared dynamic libraries 41
> _end 40, 42"
>
> And http://www.davehylands.com/avi/linker_scripts.htm in combination
> with http://www.davehylands.com/avi/downloads/libmrm/sbrk.c
>
> And ChangeLog entry 2005-10-28 of newlib 1.14.0
>
> BUT before i introduce a new nasty bug - there is already a symbol _end
> as you can see with the nm tool.
>
> Some (!) other systems (see sbrk.[cs] or syscalls.c files in sys/*
> folders) use something like sbrk_end or _end_heap globals. Most
> architectures other than arm use 'end' too.

Thanks for the information I will read the pages soon.

The newlib default sbrk implementation uses something like
heapstart=asm("end") and the newlib-lpc from which I have copied the
sbrk in most of my examples with a syscalls.c uses something like extern
char* end. Basicly the same for the Keil GNU-Examples. The default
linker-script (arm-elf-ld --verbose) defines various "*end*" and
provides an "end"
_end_ = . ;
_end = .;
PROVIDE (end = .);
So it seems to me that the name "end" is some kind of "de-facto"-default
at least when using the arm-elf toolchain even if there is a potential
for a "side-effect".

The linker has some options to enable warnings  maybe one of these
switches enables a warning so there will be at least a warning when i.e.
end is used twice or more.

Martin Thomas

von Stefan (Guest)


Rate this post
useful
not useful
Martin Thomas wrote:
> Thanks for the information I will read the pages soon.
>
> The newlib default sbrk implementation uses something like
> heapstart=asm("end") and the newlib-lpc from which I have copied the
> sbrk in most of my examples with a syscalls.c uses something like extern
> char* end. Basicly the same for the Keil GNU-Examples. The default
> linker-script (arm-elf-ld --verbose) defines various "*end*" and
> provides an "end"
> _end_ = . ;
> _end = .;
> PROVIDE (end = .);
> So it seems to me that the name "end" is some kind of "de-facto"-default
> at least when using the arm-elf toolchain even if there is a potential
> for a "side-effect".
>
> The linker has some options to enable warnings  maybe one of these
> switches enables a warning so there will be at least a warning when i.e.
> end is used twice or more.
>
> Martin Thomas

Yes, i see that a change of the de-facto standard is hard work and one
should have very good arguments to request this.

I tried the --warn-common option with the linker in order to get a
warning. But ld gives no warning in this case.

I found another text about global symbols in the linker control script
documentation:

"In some cases, it is desirable for a linker script to define a symbol
only if it is referenced, and only if it is not defined by any object
included in the link. For example, traditional linkers defined the
symbol `etext'. However, ANSI C requires that the user be able to use
`etext' as a function name without encountering an error. The PROVIDE
keyword may be used to define a symbol, such as `etext', only if it is
referenced but not defined. The syntax is PROVIDE(symbol = expression)."
http://sources.redhat.com/binutils/docs-2.12/ld.info/PROVIDE.html#PROVIDE

The same as for etext might be valid for end. Unfortunately i don't
understand the real reason ("desire in some cases") behind the text
above.

What i understand is:

The linker control script provides a symbol 'end' (PROVIDE (end = .))
only when there is a reference to 'end' (extern ... in srbk.c) and omits
the symbol when the user defines his own 'end' function/variable?

It is clear now why the linker never throws a warning for double
symbols: the end symbol from the linker command script is never defined
because user provides it... ("the linker will silently use the
definition in the program")

As you discovered already, in most startup files is a 'real' _*end*
symbol with the very same meaning as end without the limitation above. I
think in srbk.c should work with some sort of _end, but a can live with
the current de-facto standard situation.

Summary:

I think, i'll never use end as function/variable again ;-)

Stefan

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.