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.
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
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
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
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
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
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.
Sri Martin got all he requested, danke.
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
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).
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
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.
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
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
@ 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
Clifford, i like your idea with the reset with watchdog and different #define sections for DEBUG or NDEBUG sessions. Stefan
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
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
Log in with Google account
No account? Register here.