Code: Select all
void foo()
{
static void*xxx = 0;
assert(xxx==0);
}
Code: Select all
assertion failed:kernel.c:71:foo():xxx==0
Code: Select all
void foo()
{
static void*xxx = 0;
assert(xxx==0);
}
Code: Select all
assertion failed:kernel.c:71:foo():xxx==0
Thanks. I tried that, and it seemed to solve the problem. You don't know how much time I wasted trying to get that sorted!cleverca22 wrote: ↑Sun Dec 06, 2020 9:34 pmany variable that is set to 0 gets allocated into the .bss section by default
the linker will omit .bss from the actual binary, and the init code is then responsible for zeroing out bss on startup, before entering main()
you should then use the linker script to create 2 symbols at the start/end (objdump -t may show them already existing)
then you need to zero that area of ram out before main() gets ran, either in asm or in some pre-main c code
Code: Select all
-fno-zero-initialized-in-bss
If the target supports a BSS section, GCC by default puts variables that are
initialized to zero into BSS. This can save space in the resulting code.
This option turns off this behavior because some programs explicitly rely on variables
going to the data section---e.g., so that the resulting executable can find the
beginning of that section and/or make assumptions based on that.
The default is -fzero-initialized-in-bss.
but that only covers vars that you explicitely set to 0jahboater wrote: ↑Sun Dec 06, 2020 11:38 pmThis compiler option may be of interest:Code: Select all
-fno-zero-initialized-in-bss If the target supports a BSS section, GCC by default puts variables that are initialized to zero into BSS. This can save space in the resulting code. This option turns off this behavior because some programs explicitly rely on variables going to the data section---e.g., so that the resulting executable can find the beginning of that section and/or make assumptions based on that. The default is -fzero-initialized-in-bss.
Apologies blippy, I believe the zeroing of .bss is missing from the lab's in my book. If you share I can add it.blippy wrote: ↑Sun Dec 06, 2020 10:12 pmThanks. I tried that, and it seemed to solve the problem. You don't know how much time I wasted trying to get that sorted!cleverca22 wrote: ↑Sun Dec 06, 2020 9:34 pmany variable that is set to 0 gets allocated into the .bss section by default
the linker will omit .bss from the actual binary, and the init code is then responsible for zeroing out bss on startup, before entering main()
you should then use the linker script to create 2 symbols at the start/end (objdump -t may show them already existing)
then you need to zero that area of ram out before main() gets ran, either in asm or in some pre-main c code
No problemo. I didn't intend it to be a complaint. Sometimes sorting out these bugs can be very confusing.
Sure. My solution is pretty much a standard one.sean.lawless wrote: ↑Tue Dec 22, 2020 12:06 amI believe the zeroing of .bss is missing from the lab's in my book. If you share I can add it.
Code: Select all
.bss : { *(.bss*) } > ram
Code: Select all
.bss : {
_sbss = .;
__bss_start__ = _sbss;
*(.bss*);
*(.bss*);
*(COMMON);
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} > ram
Code: Select all
bl main
Code: Select all
bl pre_main
bl main
Code: Select all
extern uintptr_t __bss_start__[];
extern uintptr_t __bss_end__[];
/* Zero the BSS section 4-bytes at a time */
void pre_main(void)
{
uint32_t *memloc = (uint32_t*)__bss_start__;
while (memloc < (uint32_t*)__bss_end__)
*memloc++ = 0;
}
If the BSS section is a multiple of 32-bytes or more, perhaps something like this could be used?blippy wrote: ↑Tue Dec 22, 2020 9:48 amCode: Select all
extern uintptr_t __bss_start__[]; extern uintptr_t __bss_end__[]; /* Zero the BSS section 4-bytes at a time */ void pre_main(void) { uint32_t *memloc = (uint32_t*)__bss_start__; while (memloc < (uint32_t*)__bss_end__) *memloc++ = 0; }
Code: Select all
static inline void
clear( void *dst, size_t len )
{
asm("dup v0.2d,xzr; 1: sub %1,%1,32; stp q0,q0,[%0],32; cbnz %1,1b"
: "+r" (dst), "+r" (len) :: "q0", "memory");
}
Code: Select all
.bss : {
_edata = .;
__bss_start = .;
*(.bss.page_table)
*(.bss)
*(.bss.*)
__bss_end = .;
}
Code: Select all
if (corenr == 0) {
bzero(&__bss_start, &__bss_end - &__bss_start);
udelay(30000); // the first few prints get cut off if this delay is lower
heap_init();
printf("r0 is %lx\n", r0);
init_page_tables(ramSizeInMb());
main();
}
Code: Select all
.bss : {
__bss_start = .;
*(.bss)
*(COMMON)
. = ALIGN(32 / 8);
_end = . ;
}
/* First location in stack is highest address in RAM */
_fstack = ORIGIN(ram) + LENGTH(ram) - 4;
Code: Select all
__bss_start = .;
.bss :
{
. = ALIGN( 2 );
*(.bss*)
*(COMMON*)
. = ALIGN( 2 );
}
__bss_end__ = . ;
Code: Select all
.global __bss_start // -> .bss area in RAM
.global __bss_end__ // end of .bss area
/* Clear .bss
* ----------
*/
mov r0,#0 /* get a zero */
ldr r1,=__bss_start /* -> bss start */
ldr r2,=__bss_end__ /* -> bss end */
2: cmp r1,r2 /* check if data to clear */
strlo r0,[r1],#4 /* clear 4 bytes */
blo 2b /* loop until done */
ive seen a number of somewhat fishy accounts that seem to necro a post and repeat most of the information that was already stated, this one fits the battern, but its often borderline so i dont bother the moderators
Lab24 'game' application updated to clear BSS. bzero() uses memset() so optimizations (32 bit aligned) can go into memset() in the future.
Code: Select all
static int var = 1;
int *p_var = &(var);
Code: Select all
static int var;
int *p_var;
void init(void) {
p_var = &(var);
}
Code: Select all
void kernel_main(void)
{
init();
...
}
Yes, it's a similar deal. This time, instead of zeroing out the memory, you must transfer it. I see that I haven't actually implemented a solution for the Pi, but I do have something for the STM32, which will hopefully help. It might not work exactly, but it should be a significant clue for you.afonteles wrote: ↑Mon Feb 01, 2021 3:46 amI posted a question on another board that I believe might be related. If I have the following variables declared outside of a function:
It turns out later on that *p_var != var, without ever touching these variables before testing their values.Code: Select all
static int var = 1; int *p_var = &(var);
Code: Select all
void init_mem()
{
// not called explicitly, but done in crt.s prior to calling main()
// Copy initialized data from .sidata (Flash) to .data (RAM)
memcpy( &_sdata, &_sidata, ( ( void* )&_edata - ( void* )&_sdata ) );
// Clear the .bss section in RAM.
memset( &_sbss, 0x00, ( ( void* )&_ebss - ( void* )&_sbss ) );
}
Code: Select all
SECTIONS
{
...
/* The 'data' section is space set aside in RAM for
* things like variables, which can change. */
_sidata = .;
.data : AT(_sidata)
{
. = ALIGN(4);
/* Mark start/end locations for the 'data' section. */
_sdata = .;
*(.data)
*(.data*)
_edata = .;
. = ALIGN(4);
} >RAM
/* The 'bss' section is similar to the 'data' section,
* but its space is initialized to all 0s at the
* start of the program. */
.bss :
{
. = ALIGN(4);
/* Also mark the start/end of the BSS section. */
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} >RAM
...
Code: Select all
bl main
Code: Select all
bl init_mem
bl main
Code: Select all
#include <mini_uart.h>
#include <stdio.h>
static int var = 42;
int *p_var = &(var);
void kernel_main(void)
{
uart_init_as_stdio(115200);
puts("init test");
printf("var=%d\n", *p_var);
puts("I will now echo what you type");
while (1) {
char c = getchar();
putchar(c);
}
}
Code: Select all
* bss sections mentioned here:
* https://stackoverflow.com/q/43922511/4037492
*/
SECTIONS
{
.text.boot 0x8000 : { *(.text.boot) }
.text : { *(.text) }
.rodata : { *(.rodata) }
.data : { *(.data) }
. = ALIGN(0x8);
.bss : {
_sbss = .;
__bss_start__ = _sbss;
*(.bss*);
*(.bss*);
*(COMMON);
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
}
.crunky_heap : {
. = ALIGN(4);
_sheap = .;
__heap_start__ = _sheap;
. = . + 100000000; /* 100MB heap */
. = ALIGN(4);
_eheap = .;
__heap_end__ = _eheap;
}
}
Code: Select all
;@-------------------------------------------------------------------------
;@-------------------------------------------------------------------------
//#include <basal.h>
#if RPI == 0
#warning "vectors reports RPI is 0"
#endif
.section .text.boot
.globl _start
_start:
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
reset_handler: .word reset
undefined_handler: .word hang
swi_handler: .word hang
prefetch_handler: .word hang
data_handler: .word hang
unused_handler: .word hang
irq_handler: .word IRQ_handler
fiq_handler: .word hang
reset:
#if RPI != 0
mrs r0,cpsr ;@ moving to HYPERVISOR mode
bic r0,r0,#0x1F
orr r0,r0,#0x13
msr spsr_cxsf,r0
add r0,pc,#4
msr ELR_hyp,r0
eret
#endif
mov r0,#0x8000
mov r1,#0x0000
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
;@ (PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD2
msr cpsr_c,r0
mov sp,#0x8000
;@ (PSR_FIQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD1
msr cpsr_c,r0
mov sp,#0x4000
;@ The following are used to set the stack for alternative operating modes.
;@ In the present case, they are commented, thus ignored.
;@ (PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
;@ mov r0,#0xD3
;@ msr cpsr_c,r0
;@ mov sp,#0x8000000
;@ SVC MODE, IRQ ENABLED, FIQ DIS
;@mov r0,#0x53
;@msr cpsr_c, r0
bl zero_bss
bl kernel_main
hang: b hang
.globl put32
put32:
str r1,[r0]
bx lr
.globl get32
get32:
ldr r0,[r0]
bx lr
.globl enable_irq
enable_irq:
mrs r0,cpsr
bic r0,r0,#0x80
msr cpsr_c,r0
bx lr
;@ From Bruce Smith's ARM32 ASM book page 283
.globl disable_irq
disable_irq:
mrs r0,cpsr
orr r0,r0,#0x80
msr cpsr_c,r0
bx lr
Code: Select all
SECTIONS
{
.text.boot : { *(.text.boot) }
.text : { *(.text) }
.rodata : { *(.rodata) }
. = ALIGN(0x8);
bss_begin = .;
.bss : { *(.bss*) }
bss_end = .;
.data : { *(.data*) }
}
Code: Select all
SECTIONS
{
. = 0x80000; /* Kernel load address for AArch64 - that did the trick! */
.text.boot : { *(.text.boot) }
.text : { *(.text) }
.rodata : { *(.rodata) }
.data : { *(.data) }
. = ALIGN(0x8);
bss_begin = .;
.bss : { *(.bss*) }
bss_end = .;
}