调整brk系统调用,使得参数、返回值与Linux一致 (#238)

* 新增用于测试relibc的app

* 为适配relibc,修改do_execve中关于用户栈的内容的设置

* 调整brk系统调用,使得参数、返回值与Linux一致
This commit is contained in:
login 2023-04-11 16:54:14 +08:00 committed by GitHub
parent 13776c114b
commit ac48398d3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 338 additions and 30 deletions

View File

@ -172,7 +172,8 @@
"cmd.h": "c",
"user_namespace.h": "c",
"sleep.h": "c",
"net.h": "c"
"net.h": "c",
"lz4.h": "c"
},
"C_Cpp.errorSquiggles": "Enabled",
"esbonio.sphinx.confDir": "",

View File

@ -461,13 +461,15 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
if (tmp < 0)
goto exec_failed;
int argc = 0;
char **dst_argv = NULL;
// kdebug("stack_start_addr=%#018lx", stack_start_addr);
// 拷贝参数列表
if (argv != NULL)
{
int argc = 0;
// 目标程序的argv基地址指针最大8个参数
char **dst_argv = (char **)(stack_start_addr - (sizeof(char **) << 3));
dst_argv = (char **)(stack_start_addr - (sizeof(char **) << 3));
uint64_t str_addr = (uint64_t)dst_argv;
for (argc = 0; argc < 8 && argv[argc] != NULL; ++argc)
@ -486,14 +488,29 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
}
// 重新设定栈基址,并预留空间防止越界
stack_start_addr = str_addr - 8;
current_pcb->mm->stack_start = stack_start_addr;
regs->rsp = regs->rbp = stack_start_addr;
// 传递参数
regs->rdi = argc;
regs->rsi = (uint64_t)dst_argv;
stack_start_addr = str_addr - 8;
}
// kdebug("stack_start_addr=%#018lx", stack_start_addr);
// ==== 生成relibc所需的Stack结构体
{
uint64_t *ptr_stack = (uint64_t *)(stack_start_addr - 8);
if (argc == 0)
*ptr_stack = 0;
else
*ptr_stack = (uint64_t)dst_argv;
ptr_stack--;
*ptr_stack = argc;
stack_start_addr -= 16;
}
// 传递参数(旧版libc)
regs->rdi = argc;
regs->rsi = (uint64_t)dst_argv;
// 设置用户栈基地址
current_pcb->mm->stack_start = stack_start_addr;
regs->rsp = regs->rbp = stack_start_addr;
// kdebug("execve ok");
// 设置进程的段选择子为用户态可访问
regs->cs = USER_CS | 3;
@ -539,7 +556,7 @@ ul initial_kernel_thread(ul arg)
kinfo("initial proc running...\targ:%#018lx, vruntime=%d", arg, current_pcb->virtual_runtime);
int val = 0;
val = scm_enable_double_buffer();
rs_init_stdio();
// block_io_scheduler_init();
ahci_init();

View File

@ -176,22 +176,14 @@ uint64_t sys_vfork(struct pt_regs *regs)
uint64_t sys_brk(struct pt_regs *regs)
{
uint64_t new_brk = PAGE_2M_ALIGN(regs->r8);
// kdebug("sys_brk input= %#010lx , new_brk= %#010lx bytes current_pcb->mm->brk_start=%#018lx
// current->end_brk=%#018lx", regs->r8, new_brk, current_pcb->mm->brk_start, current_pcb->mm->brk_end);
if ((int64_t)regs->r8 == -1)
{
// kdebug("get brk_start=%#018lx", current_pcb->mm->brk_start);
return current_pcb->mm->brk_start;
}
if ((int64_t)regs->r8 == -2)
{
// kdebug("get brk_end=%#018lx", current_pcb->mm->brk_end);
return current_pcb->mm->brk_end;
}
if (new_brk > current_pcb->addr_limit) // 堆地址空间超过限制
return -ENOMEM;
struct mm_struct *mm = current_pcb->mm;
if (new_brk < mm->brk_start || new_brk> new_brk >= current_pcb->addr_limit)
return mm->brk_end;
if (mm->brk_end == new_brk)
return new_brk;
int64_t offset;
if (new_brk >= current_pcb->mm->brk_end)
@ -202,7 +194,7 @@ uint64_t sys_brk(struct pt_regs *regs)
new_brk = mm_do_brk(current_pcb->mm->brk_end, offset); // 扩展堆内存空间
current_pcb->mm->brk_end = new_brk;
return 0;
return mm->brk_end;
}
/**

View File

@ -0,0 +1,21 @@
CC=x86_64-elf-gcc
LD=x86_64-elf-ld
OBJCOPY=x86_64-dragonos-objcopy
# 修改这里把它改为你的relibc的sysroot路径
RELIBC_SYSROOT=/home/longjin/relibc/sysroot
CFLAGS=-I $(RELIBC_SYSROOT)/usr/include
# 修改这里把它改为你的DragonOS的根目录
ROOT_PATH=/home/longjin/code/DragonOS
tmp_output_dir=$(ROOT_PATH)/bin/tmp/user
output_dir=$(ROOT_PATH)/bin/user
LIBC_OBJS:=$(shell find $(RELIBC_SYSROOT)/usr/lib -name "*.o")
LIBC_OBJS+=$(RELIBC_SYSROOT)/usr/lib/libc.a
all: main.o
$(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test $(shell find . -name "*.o") $(LIBC_OBJS) -T link.lds
$(OBJCOPY) -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test $(output_dir)/test.elf
main.o: main.c
$(CC) $(CFLAGS) -c main.c -o main.o

View File

@ -0,0 +1,239 @@
/* Script for -z combreloc */
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
"elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
*(.rela.ifunc)
}
.rela.plt :
{
*(.rela.plt)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
. = ALIGN(CONSTANT (MAXPAGESIZE));
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) *(.iplt) }
.plt.got : { *(.plt.got) }
.plt.sec : { *(.plt.sec) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf.em. */
*(.gnu.warning)
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
. = ALIGN(CONSTANT (MAXPAGESIZE));
/* Adjust the address for the rodata segment. We want to adjust up to
the same address within the page on the next page up. */
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
/* Thread Local Storage sections */
.tdata :
{
PROVIDE_HIDDEN (__tdata_start = .);
*(.tdata .tdata.* .gnu.linkonce.td.*)
}
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
.got : { *(.got) *(.igot) }
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
.got.plt : { *(.got.plt) *(.igot.plt) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we do not
pad the .data section. */
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
.lbss :
{
*(.dynlbss)
*(.lbss .lbss.* .gnu.linkonce.lb.*)
*(LARGE_COMMON)
}
. = ALIGN(64 / 8);
. = SEGMENT_START("ldata-segment", .);
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
{
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
}
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
{
*(.ldata .ldata.* .gnu.linkonce.l.*)
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
. = ALIGN(64 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.debug_addr 0 : { *(.debug_addr) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}

View File

@ -0,0 +1,34 @@
/**
* @file main.c
* @author longjin (longjin@RinGoTek.cn)
* @brief signal用的程序
* @version 0.1
* @date 2022-12-06
*
* @copyright Copyright (c) 2022
*
*/
/**
* signal的kill命令的方法:
* 1.DragonOS的控制台输入 exec bin/test_signal.elf &
* , '&',
* 2.kill对应的进程的pid (,:"[1] 生成的pid")
*
*/
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main()
{
printf("Test Relibc printf!\n");
printf("Test Relibc printf ok!\n");
return 0;
}

View File

@ -131,10 +131,10 @@ static int malloc_enlarge(int64_t size)
{
if (brk_base_addr == 0) // 第一次调用,需要初始化
{
brk_base_addr = brk(-1);
brk_base_addr = sbrk(0);
// printf("brk_base_addr=%#018lx\n", brk_base_addr);
brk_managed_addr = brk_base_addr;
brk_max_addr = brk(-2);
brk_max_addr = brk_base_addr;
}
int64_t free_space = brk_max_addr - brk_managed_addr;
@ -142,7 +142,7 @@ static int malloc_enlarge(int64_t size)
if (free_space < size) // 现有堆空间不足
{
if (sbrk(size - free_space) != (void *)(-1))
brk_max_addr = brk((-2));
brk_max_addr = sbrk((0));
else
{
put_string("malloc_enlarge(): no_mem\n", COLOR_YELLOW, COLOR_BLACK);
@ -363,7 +363,7 @@ static void release_brk()
if (delta <= 0) // 不用释放内存
return;
sbrk(-delta);
brk_max_addr = brk(-2);
brk_max_addr = sbrk(0);
brk_managed_addr = brk_max_addr;
malloc_free_list_end->length = brk_max_addr - (uint64_t)malloc_free_list_end;

View File

@ -88,7 +88,11 @@ pid_t vfork(void)
uint64_t brk(uint64_t end_brk)
{
uint64_t x = (uint64_t)syscall_invoke(SYS_BRK, (uint64_t)end_brk, 0, 0, 0, 0, 0, 0, 0);
return x;
if (x < end_brk){
errno = -ENOMEM;
return -1;
}
return 0;
}
/**