feat: 支持动态链接 (#910)

* feat: 支持动态链接

Authored-By: chiichen <chiichen@qq.com>
Co-authored-by: longjin <longjin@DragonOS.org>
Signed-off-by: longjin <longjin@DragonOS.org>

* build: 更新构建容器版本至v1.12并指定DADK安装版本

- 将BUILD_CONTAINER_VERSION从v1.11升级到v1.12
- 修改bootstrap.sh和user/Makefile中DADK的安装方式,明确指定版本v0.4.0

Signed-off-by: longjin <longjin@DragonOS.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
Co-authored-by: chiichen <chiichen@qq.com>
Co-authored-by: longjin <longjin@dragonos.org>
Co-authored-by: Jomo <xuzihao@dragonos.org>
Co-authored-by: MemoryShore <1353318529@qq.com>
This commit is contained in:
chiichen 2025-05-19 14:29:55 +08:00 committed by GitHub
parent b322121dd9
commit fccfa6f7ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 477 additions and 273 deletions

View File

@ -11,14 +11,14 @@ jobs:
name: Format check ${{ matrix.arch }}
runs-on: ubuntu-latest
continue-on-error: true
container: dragonos/dragonos-dev:v1.11
container: dragonos/dragonos-dev:v1.12
strategy:
matrix:
arch: [x86_64, riscv64, loongarch64]
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.11"
- run: echo "Running in dragonos/dragonos-dev:v1.12"
- uses: actions/checkout@v3
- name: Format check
@ -35,14 +35,14 @@ jobs:
name: Kernel static test ${{ matrix.arch }}
runs-on: ubuntu-latest
continue-on-error: true
container: dragonos/dragonos-dev:v1.11
container: dragonos/dragonos-dev:v1.12
strategy:
matrix:
arch: [x86_64, riscv64, loongarch64]
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.11"
- run: echo "Running in dragonos/dragonos-dev:v1.12"
- uses: actions/checkout@v3
@ -56,7 +56,7 @@ jobs:
build:
name: Build ${{ matrix.arch }}
runs-on: ubuntu-latest
container: dragonos/dragonos-dev:v1.11
container: dragonos/dragonos-dev:v1.12
continue-on-error: true
strategy:
matrix:
@ -73,7 +73,7 @@ jobs:
checkout_params: {}
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.11"
- run: echo "Running in dragonos/dragonos-dev:v1.12"
- uses: actions/checkout@v3
with: ${{ matrix.checkout_params }}

View File

@ -177,6 +177,10 @@ impl X86_64MMArch {
error_code: X86PfErrorCode,
address: VirtAddr,
) {
// log::debug!("fault at {:?}:{:?}",
// address,
// error_code,
// );
let rflags = RFlags::from_bits_truncate(regs.rflags);
let mut flags: FaultFlags = FaultFlags::FAULT_FLAG_ALLOW_RETRY
| FaultFlags::FAULT_FLAG_KILLABLE

View File

@ -53,6 +53,7 @@ impl Syscall {
}
/// ## 用于控制和查询与体系结构相关的进程特定选项
/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kernel/process_64.c#913
pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> {
let pcb = ProcessManager::current_pcb();
if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) {
@ -109,8 +110,17 @@ impl Syscall {
}
#[allow(dead_code)]
pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
todo!("do_arch_prctl_common not unimplemented");
pub fn do_arch_prctl_common(option: usize, arg2: usize) -> Result<usize, SystemError> {
// Don't use 0x3001-0x3004 because of old glibcs
if (0x3001..=0x3004).contains(&option) {
return Err(SystemError::EINVAL);
}
todo!(
"do_arch_prctl_common not unimplemented, option: {}, arg2: {}",
option,
arg2
);
}
}

View File

@ -90,7 +90,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
mfence();
let pid = ProcessManager::current_pcb().pid();
let show = false;
// let show = if syscall_num != SYS_SCHED && pid.data() >= 7 {
// let show = if syscall_num != SYS_SCHED && pid.data() >= 9{
// true
// } else {
// false

View File

@ -1,4 +1,4 @@
mod hook;
pub mod hook;
use alloc::boxed::Box;
use cfg_if::cfg_if;

View File

@ -144,6 +144,7 @@ impl DeviceManager {
/// - Err(SystemError): 匹配过程中出现意外错误,没有匹配成功
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#899
#[inline(never)]
fn do_device_attach_driver(
&self,
driver: &Arc<dyn Driver>,

View File

@ -1452,7 +1452,6 @@ impl IndexNode for LockedFATInode {
let page_cache = self.0.lock().page_cache.clone();
if let Some(page_cache) = page_cache {
let r = page_cache.lock_irqsave().read(offset, &mut buf[0..len]);
// self.0.lock_irqsave().update_metadata();
return r;
} else {
return self.read_direct(offset, len, buf, data);

View File

@ -113,13 +113,14 @@ impl InnerPageCache {
/// - `Ok(usize)` 成功读取的长度
/// - `Err(SystemError)` 失败返回错误码
pub fn read(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
let inode = self
let inode: Arc<dyn IndexNode> = self
.page_cache_ref
.upgrade()
.unwrap()
.inode
.upgrade()
.unwrap();
let file_size = inode.metadata().unwrap().size;
let len = if offset < file_size as usize {
@ -182,6 +183,7 @@ impl InnerPageCache {
for (page_index, count) in not_exist {
// TODO 这里使用buffer避免多次读取磁盘将来引入异步IO直接写入页面减少内存开销和拷贝
let mut page_buf = vec![0u8; MMArch::PAGE_SIZE * count];
inode.read_sync(page_index * MMArch::PAGE_SIZE, page_buf.as_mut())?;
self.create_pages(page_index, page_buf.as_mut())?;
@ -314,7 +316,7 @@ impl InnerPageCache {
impl Drop for InnerPageCache {
fn drop(&mut self) {
log::debug!("page cache drop");
// log::debug!("page cache drop");
let mut page_manager = page_manager_lock_irqsave();
for page in self.pages.values() {
page_manager.remove_page(&page.phys_address());
@ -358,6 +360,13 @@ impl PageCache {
}
pub fn lock_irqsave(&self) -> SpinLockGuard<InnerPageCache> {
if self.inner.is_locked() {
log::error!("page cache already locked");
}
self.inner.lock_irqsave()
}
pub fn is_locked(&self) -> bool {
self.inner.is_locked()
}
}

View File

@ -42,6 +42,7 @@ pub(super) fn do_faccessat(
let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
let path = path.to_str().map_err(|_| SystemError::EINVAL)?;
// log::debug!("do_faccessat path: {:?}", path);
let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
@ -166,7 +167,7 @@ fn do_sys_openat2(
how: OpenHow,
follow_symlink: bool,
) -> Result<usize, SystemError> {
// debug!("open path: {}, how: {:?}", path, how);
// log::debug!("openat2: dirfd: {}, path: {}, how: {:?}",dirfd, path, how);
let path = path.trim();
let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;

View File

@ -273,6 +273,7 @@ pub fn vfs_getattr(
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#274
#[inline(never)]
pub fn vfs_fstatat(dfd: i32, filename: &str, flags: AtFlags) -> Result<KStat, SystemError> {
// log::debug!("vfs_fstatat: dfd={}, filename={}", dfd, filename);
let statx_flags = flags | AtFlags::AT_NO_AUTOMOUNT;
if dfd >= 0 && flags == AtFlags::AT_EMPTY_PATH {
return vfs_fstat(dfd);
@ -322,7 +323,7 @@ pub(super) fn do_newfstatat(
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#393
#[inline(never)]
fn cp_new_stat(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> {
pub(super) fn cp_new_stat(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> {
let posix_stat = PosixStat::try_from(kstat)?;
let mut ubuf_writer =
UserBufferWriter::new(user_buf_ptr as *mut PosixStat, size_of::<PosixStat>(), true)?;
@ -397,70 +398,6 @@ fn cp_statx(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> {
Ok(())
}
// 注意!这个结构体定义的貌似不太对,需要修改!
#[repr(C)]
#[derive(Clone, Copy)]
/// # 文件信息结构体
pub struct PosixKstat {
/// 硬件设备ID
pub dev_id: u64,
/// inode号
pub inode: u64,
/// 硬链接数
pub nlink: u64,
/// 文件权限
pub mode: ModeType,
/// 所有者用户ID
pub uid: i32,
/// 所有者组ID
pub gid: i32,
/// 设备ID
pub rdev: i64,
/// 文件大小
pub size: i64,
/// 文件系统块大小
pub blcok_size: i64,
/// 分配的512B块数
pub blocks: u64,
/// 最后访问时间
pub atime: PosixTimeSpec,
/// 最后修改时间
pub mtime: PosixTimeSpec,
/// 最后状态变化时间
pub ctime: PosixTimeSpec,
/// 用于填充结构体大小的空白数据
pub _pad: [i8; 24],
}
impl PosixKstat {
pub(super) fn new() -> Self {
Self {
inode: 0,
dev_id: 0,
mode: ModeType::empty(),
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
size: 0,
atime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
mtime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
ctime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
blcok_size: 0,
blocks: 0,
_pad: Default::default(),
}
}
}
/// 通用的PosixStat
#[allow(unused)]
#[repr(C)]

View File

@ -21,7 +21,7 @@ use crate::{
time::{syscall::PosixTimeval, PosixTimeSpec},
};
use super::stat::{do_newfstatat, do_statx, PosixKstat};
use super::stat::{do_newfstatat, do_statx, vfs_fstat};
use super::vcore::do_symlinkat;
use super::{
fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
@ -1211,79 +1211,31 @@ impl Syscall {
return Err(SystemError::EBADF);
}
fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> {
let binding = ProcessManager::current_pcb().fd_table();
let fd_table_guard = binding.read();
let file = fd_table_guard
.get_file_by_fd(fd)
.ok_or(SystemError::EBADF)?;
// drop guard 以避免无法调度的问题
drop(fd_table_guard);
let mut kstat = PosixKstat::new();
// 获取文件信息
let metadata = file.metadata()?;
kstat.size = metadata.size;
kstat.dev_id = metadata.dev_id as u64;
kstat.inode = metadata.inode_id.into() as u64;
kstat.blcok_size = metadata.blk_size as i64;
kstat.blocks = metadata.blocks as u64;
kstat.atime.tv_sec = metadata.atime.tv_sec;
kstat.atime.tv_nsec = metadata.atime.tv_nsec;
kstat.mtime.tv_sec = metadata.mtime.tv_sec;
kstat.mtime.tv_nsec = metadata.mtime.tv_nsec;
kstat.ctime.tv_sec = metadata.ctime.tv_sec;
kstat.ctime.tv_nsec = metadata.ctime.tv_nsec;
kstat.nlink = metadata.nlinks as u64;
kstat.uid = metadata.uid as i32;
kstat.gid = metadata.gid as i32;
kstat.rdev = metadata.raw_dev.data() as i64;
kstat.mode = metadata.mode;
match file.file_type() {
FileType::File => kstat.mode.insert(ModeType::S_IFREG),
FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK),
FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK),
FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO),
FileType::KvmDevice => kstat.mode.insert(ModeType::S_IFCHR),
FileType::FramebufferDevice => kstat.mode.insert(ModeType::S_IFCHR),
}
return Ok(kstat);
#[inline(never)]
pub fn fstat(fd: i32, user_stat_ptr: usize) -> Result<usize, SystemError> {
Self::newfstat(fd, user_stat_ptr)
}
pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
let mut writer = UserBufferWriter::new(usr_kstat, size_of::<PosixKstat>(), true)?;
let kstat = Self::do_fstat(fd)?;
writer.copy_one_to_user(&kstat, 0)?;
return Ok(0);
}
pub fn stat(path: *const u8, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
pub fn stat(path: *const u8, user_stat_ptr: usize) -> Result<usize, SystemError> {
let fd = Self::open(
path,
FileMode::O_RDONLY.bits(),
ModeType::empty().bits(),
true,
)?;
let r = Self::fstat(fd as i32, user_kstat);
let r = Self::fstat(fd as i32, user_stat_ptr);
Self::close(fd).ok();
return r;
}
pub fn lstat(path: *const u8, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
pub fn lstat(path: *const u8, user_stat_ptr: usize) -> Result<usize, SystemError> {
let fd = Self::open(
path,
FileMode::O_RDONLY.bits(),
ModeType::empty().bits(),
false,
)?;
let r = Self::fstat(fd as i32, user_kstat);
let r = Self::fstat(fd as i32, user_stat_ptr);
Self::close(fd).ok();
return r;
}
@ -1356,6 +1308,16 @@ impl Syscall {
do_newfstatat(dfd, filename_str, user_stat_buf_ptr, flags).map(|_| 0)
}
#[inline(never)]
pub fn newfstat(fd: i32, user_stat_buf_ptr: usize) -> Result<usize, SystemError> {
if user_stat_buf_ptr == 0 {
return Err(SystemError::EFAULT);
}
let stat = vfs_fstat(fd)?;
// log::debug!("newfstat fd: {}, stat.size: {:?}",fd,stat.size);
super::stat::cp_new_stat(stat, user_stat_buf_ptr).map(|_| 0)
}
pub fn mknod(
path: *const u8,
mode: ModeType,

View File

@ -7,10 +7,10 @@ use core::{
use alloc::vec::Vec;
use elf::{
abi::{PT_GNU_PROPERTY, PT_INTERP},
abi::{ET_DYN, ET_EXEC, PT_GNU_PROPERTY, PT_INTERP, PT_LOAD},
endian::AnyEndian,
file::FileHeader,
segment::ProgramHeader,
segment::{ProgramHeader, SegmentTable},
};
use log::error;
use system_error::SystemError;
@ -18,7 +18,6 @@ use system_error::SystemError;
use crate::{
arch::{CurrentElfArch, MMArch},
driver::base::block::SeekFrom,
filesystem::vfs::file::File,
libs::align::page_align_up,
mm::{
allocator::page_frame::{PageFrameCount, VirtPageFrame},
@ -28,7 +27,9 @@ use crate::{
},
process::{
abi::AtType,
exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam},
exec::{
BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam, ExecParamFlags,
},
ProcessFlags, ProcessManager,
},
syscall::user_access::{clear_user, copy_to_user},
@ -134,8 +135,8 @@ impl ElfLoader {
end: VirtAddr,
prot_flags: ProtFlags,
) -> Result<(), ExecError> {
let start = self.elf_page_start(start);
let end = self.elf_page_align_up(end);
let start = Self::elf_page_start(start);
let end = Self::elf_page_align_up(end);
// debug!("set_elf_brk: start={:?}, end={:?}", start, end);
if end > start {
let r = user_vm_guard.map_anonymous(
@ -158,15 +159,15 @@ impl ElfLoader {
}
/// 计算addr在ELF PAGE内的偏移
fn elf_page_offset(&self, addr: VirtAddr) -> usize {
fn elf_page_offset(addr: VirtAddr) -> usize {
addr.data() & (CurrentElfArch::ELF_PAGE_SIZE - 1)
}
fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr {
fn elf_page_start(addr: VirtAddr) -> VirtAddr {
VirtAddr::new(addr.data() & (!(CurrentElfArch::ELF_PAGE_SIZE - 1)))
}
fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr {
fn elf_page_align_up(addr: VirtAddr) -> VirtAddr {
VirtAddr::new(
(addr.data() + CurrentElfArch::ELF_PAGE_SIZE - 1)
& (!(CurrentElfArch::ELF_PAGE_SIZE - 1)),
@ -174,7 +175,7 @@ impl ElfLoader {
}
/// 根据ELF的p_flags生成对应的ProtFlags
fn make_prot(&self, p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags {
fn make_prot(p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags {
let mut prot = ProtFlags::empty();
if p_flags & elf::abi::PF_R != 0 {
prot |= ProtFlags::PROT_READ;
@ -211,7 +212,6 @@ impl ElfLoader {
/// - `Ok((VirtAddr, bool))`如果成功加载则bool值为true否则为false. VirtAddr为加载的地址
#[allow(clippy::too_many_arguments)]
fn load_elf_segment(
&self,
user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>,
param: &mut ExecParam,
phent: &ProgramHeader,
@ -223,11 +223,11 @@ impl ElfLoader {
// debug!("load_elf_segment: addr_to_map={:?}", addr_to_map);
// 映射位置的偏移量(页内偏移)
let beginning_page_offset = self.elf_page_offset(addr_to_map);
addr_to_map = self.elf_page_start(addr_to_map);
let beginning_page_offset = Self::elf_page_offset(addr_to_map);
addr_to_map = Self::elf_page_start(addr_to_map);
// 计算要映射的内存的大小
let map_size = phent.p_filesz as usize + beginning_page_offset;
let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data();
let map_size = Self::elf_page_align_up(VirtAddr::new(map_size)).data();
// 当前段在文件中的大小
let seg_in_file_size = phent.p_filesz as usize;
// 当前段在文件中的偏移量
@ -266,7 +266,9 @@ impl ElfLoader {
// So we first map the 'big' image - and unmap the remainder at
// the end. (which unmap is needed for ELF images with holes.)
if total_size != 0 {
let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data();
let total_size = Self::elf_page_align_up(VirtAddr::new(total_size)).data();
// log::debug!("total_size={}", total_size);
map_addr = user_vm_guard
.map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false, true)
@ -282,7 +284,7 @@ impl ElfLoader {
)?;
// 加载文件到内存
self.do_load_file(
Self::do_load_file(
map_addr + beginning_page_offset,
seg_in_file_size,
file_offset,
@ -307,7 +309,7 @@ impl ElfLoader {
// );
// 加载文件到内存
self.do_load_file(
Self::do_load_file(
map_addr + beginning_page_offset,
seg_in_file_size,
file_offset,
@ -326,6 +328,152 @@ impl ElfLoader {
return Ok((map_addr, true));
}
/// 加载elf动态链接器
///
/// ## 参数
///
/// - `interp_elf_ex`:动态链接器
/// - `load_bias`偏移量
///
/// ## TODO
///
/// 添加一个Arch state抽象描述架构相关的elf state(参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#592)
fn load_elf_interp(
interp_elf_ex: &mut ExecParam,
load_bias: usize,
) -> Result<BinaryLoaderResult, ExecError> {
// log::debug!("loading elf interp");
let mut head_buf = [0u8; 512];
interp_elf_ex
.file_mut()
.lseek(SeekFrom::SeekSet(0))
.map_err(|_| ExecError::NotSupported)?;
let _bytes = interp_elf_ex
.file_mut()
.read(512, &mut head_buf)
.map_err(|_| ExecError::NotSupported)?;
let interp_hdr =
Self::parse_ehdr(head_buf.as_ref()).map_err(|_| ExecError::NotExecutable)?;
if interp_hdr.e_type != ET_EXEC && interp_hdr.e_type != ET_DYN {
return Err(ExecError::NotExecutable);
}
let mut phdr_buf = Vec::new();
let phdr_table = Self::parse_segments(interp_elf_ex, &interp_hdr, &mut phdr_buf)
.map_err(|_| ExecError::ParseError)?
.ok_or(ExecError::ParseError)?;
//TODO 架构相关检查 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#610
let mut total_size = Self::total_mapping_size(&phdr_table);
if total_size == 0 {
return Err(ExecError::InvalidParemeter);
}
let mut load_addr_set = false;
let mut load_addr: VirtAddr = VirtAddr::new(0);
let mut elf_bss: VirtAddr = VirtAddr::new(0);
let mut last_bss: VirtAddr = VirtAddr::new(0);
let mut bss_prot: Option<ProtFlags> = None;
for section in phdr_table {
if section.p_type == PT_LOAD {
// log::debug!("loading {:?}", section);
let mut elf_type = MapFlags::MAP_PRIVATE;
let elf_prot = Self::make_prot(section.p_flags, true, true);
let vaddr = TryInto::<usize>::try_into(section.p_vaddr).unwrap();
let mut addr_to_map = load_addr + vaddr;
if interp_hdr.e_type == ET_EXEC || load_addr_set {
elf_type.insert(MapFlags::MAP_FIXED)
} else if load_bias != 0 && interp_hdr.e_type == ET_DYN {
addr_to_map = VirtAddr::new(0);
}
let map_addr = Self::load_elf_segment(
&mut interp_elf_ex.vm().clone().write(),
interp_elf_ex,
&section,
addr_to_map,
&elf_prot,
&elf_type,
total_size,
)
.map_err(|e| {
log::error!("Failed to load elf interpreter :{:?}", e);
return ExecError::InvalidParemeter;
})?;
if !map_addr.1 {
return Err(ExecError::BadAddress(Some(map_addr.0)));
}
let map_addr = map_addr.0;
total_size = 0;
if !load_addr_set && interp_hdr.e_type == ET_DYN {
load_addr =
VirtAddr::new(map_addr - Self::elf_page_start(VirtAddr::new(vaddr)));
load_addr_set = true;
}
let addr = load_addr + TryInto::<usize>::try_into(section.p_vaddr).unwrap();
if addr >= MMArch::USER_END_VADDR
|| section.p_filesz > section.p_memsz
|| TryInto::<usize>::try_into(section.p_memsz).unwrap()
> MMArch::USER_END_VADDR.data()
|| MMArch::USER_END_VADDR - TryInto::<usize>::try_into(section.p_memsz).unwrap()
< addr
{
return Err(ExecError::OutOfMemory);
}
let addr = load_addr
+ TryInto::<usize>::try_into(section.p_vaddr + section.p_filesz).unwrap();
if addr > elf_bss {
elf_bss = addr;
}
let addr = load_addr
+ TryInto::<usize>::try_into(section.p_vaddr + section.p_memsz).unwrap();
if addr > last_bss {
last_bss = addr;
bss_prot = Some(elf_prot);
}
}
}
Self::pad_zero(elf_bss).map_err(|_| return ExecError::BadAddress(Some(elf_bss)))?;
elf_bss = Self::elf_page_align_up(elf_bss);
last_bss = Self::elf_page_align_up(last_bss);
if last_bss > elf_bss {
if bss_prot.is_none() {
return Err(ExecError::InvalidParemeter);
}
let mut bss_prot = bss_prot.unwrap();
if bss_prot.contains(ProtFlags::PROT_EXEC) {
bss_prot = ProtFlags::PROT_EXEC;
} else {
bss_prot = ProtFlags::PROT_NONE;
}
interp_elf_ex
.vm()
.clone()
.write()
.map_anonymous(
elf_bss,
last_bss - elf_bss,
bss_prot,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE,
false,
true,
)
.map_err(|e| match e {
SystemError::EINVAL => ExecError::InvalidParemeter,
SystemError::ENOMEM => ExecError::OutOfMemory,
_ => return ExecError::InvalidParemeter,
})?;
}
load_addr += TryInto::<usize>::try_into(interp_hdr.e_entry).unwrap();
if load_addr > MMArch::USER_END_VADDR {
return Err(ExecError::BadAddress(Some(
load_addr + TryInto::<usize>::try_into(interp_hdr.e_entry).unwrap(),
)));
}
// log::debug!("sucessfully load elf interp");
return Ok(BinaryLoaderResult::new(load_addr));
}
/// 加载ELF文件到用户空间
///
/// ## 参数
@ -335,7 +483,6 @@ impl ElfLoader {
/// - `offset_in_file`:在文件内的偏移量
/// - `param`:执行参数
fn do_load_file(
&self,
mut vaddr: VirtAddr,
size: usize,
offset_in_file: usize,
@ -367,8 +514,8 @@ impl ElfLoader {
}
/// 我们需要显式的把数据段之后剩余的内存页都清零。
fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> {
let nbyte = self.elf_page_offset(elf_bss);
fn pad_zero(elf_bss: VirtAddr) -> Result<(), SystemError> {
let nbyte = Self::elf_page_offset(elf_bss);
if nbyte > 0 {
let nbyte = CurrentElfArch::ELF_PAGE_SIZE - nbyte;
unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?;
@ -376,6 +523,37 @@ impl ElfLoader {
return Ok(());
}
/// 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158获取要加载的total_size
fn total_mapping_size(ehdr_table: &SegmentTable<'_, AnyEndian>) -> usize {
let mut has_load = false;
let mut min_address = VirtAddr::new(usize::MAX);
let mut max_address = VirtAddr::new(0usize);
let loadable_sections = ehdr_table
.into_iter()
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
for seg_to_load in loadable_sections {
min_address = min(
min_address,
Self::elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())),
);
max_address = max(
max_address,
VirtAddr::new(
(seg_to_load.p_vaddr + seg_to_load.p_memsz)
.try_into()
.unwrap(),
),
);
has_load = true;
}
let total_size = if has_load {
max_address - min_address
} else {
0
};
return total_size;
}
/// 创建auxv
///
/// ## 参数
@ -562,7 +740,7 @@ impl BinaryLoader for ElfLoader {
.map_err(|_| ExecError::ParseError)?
.ok_or(ExecError::ParseError)?;
let mut _gnu_property_data: Option<ProgramHeader> = None;
let interpreter: Option<File> = None;
let mut interpreter: Option<ExecParam> = None;
for seg in phdr_table {
if seg.p_type == PT_GNU_PROPERTY {
_gnu_property_data = Some(seg);
@ -594,8 +772,8 @@ impl BinaryLoader for ElfLoader {
log::error!("Failed to load interpreter ");
return Err(ExecError::NotSupported);
}
let _interpreter_path = core::str::from_utf8(
&buffer[0..TryInto::<usize>::try_into(seg.p_filesz).unwrap() - 1], //
let interpreter_path = core::str::from_utf8(
&buffer[0..TryInto::<usize>::try_into(seg.p_filesz).unwrap() - 1],
)
.map_err(|e| {
ExecError::Other(format!(
@ -603,9 +781,17 @@ impl BinaryLoader for ElfLoader {
e
))
})?;
//TODO 加入对动态链接器的加载,参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#890
// log::debug!("opening interpreter at :{}", interpreter_path);
interpreter = Some(
ExecParam::new(interpreter_path, param.vm().clone(), ExecParamFlags::EXEC)
.map_err(|e| {
log::error!("Failed to load interpreter {interpreter_path}: {:?}", e);
return ExecError::NotSupported;
})?,
);
}
//TODO 缺少一部分逻辑 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#931
if interpreter.is_some() {
/* Some simple consistency checks for the interpreter */
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#950
@ -627,39 +813,14 @@ impl BinaryLoader for ElfLoader {
// program header的虚拟地址
let mut phdr_vaddr: Option<VirtAddr> = None;
let mut _reloc_func_desc = 0usize;
// 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158获取要加载的total_size
let mut has_load = false;
let mut min_address = VirtAddr::new(usize::MAX);
let mut max_address = VirtAddr::new(0usize);
let total_size = Self::total_mapping_size(&phdr_table);
let loadable_sections = phdr_table
.into_iter()
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
for seg_to_load in loadable_sections {
min_address = min(
min_address,
self.elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())),
);
max_address = max(
max_address,
VirtAddr::new(
(seg_to_load.p_vaddr + seg_to_load.p_memsz)
.try_into()
.unwrap(),
),
);
has_load = true;
}
let total_size = if has_load {
max_address - min_address
} else {
0
};
let loadable_sections = phdr_table
.into_iter()
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
for seg_to_load in loadable_sections {
// debug!("seg_to_load = {:?}", seg_to_load);
// log::debug!("seg_to_load = {:?}", seg_to_load);
if unlikely(elf_brk > elf_bss) {
// debug!(
// "to set brk, elf_brk = {:?}, elf_bss = {:?}",
@ -672,7 +833,7 @@ impl BinaryLoader for ElfLoader {
elf_brk + load_bias,
bss_prot_flags,
)?;
let nbyte = self.elf_page_offset(elf_bss);
let nbyte = Self::elf_page_offset(elf_bss);
if nbyte > 0 {
let nbyte = min(CurrentElfArch::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss);
unsafe {
@ -684,7 +845,7 @@ impl BinaryLoader for ElfLoader {
}
// 生成ProtFlags.
let elf_prot_flags = self.make_prot(seg_to_load.p_flags, interpreter.is_some(), false);
let elf_prot_flags = Self::make_prot(seg_to_load.p_flags, interpreter.is_some(), false);
let mut elf_map_flags = MapFlags::MAP_PRIVATE;
@ -713,37 +874,33 @@ impl BinaryLoader for ElfLoader {
load_bias = 0;
}
}
load_bias = self
.elf_page_start(VirtAddr::new(
load_bias - TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
))
.data();
load_bias = Self::elf_page_start(VirtAddr::new(
load_bias - TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
))
.data();
if total_size == 0 {
return Err(ExecError::InvalidParemeter);
}
}
// 加载这个段到用户空间
// debug!("to load elf segment");
let e = self
.load_elf_segment(
&mut user_vm,
param,
&seg_to_load,
vaddr + load_bias,
&elf_prot_flags,
&elf_map_flags,
total_size,
)
.map_err(|e| {
error!("load_elf_segment failed: {:?}", e);
match e {
SystemError::EFAULT => ExecError::BadAddress(None),
SystemError::ENOMEM => ExecError::OutOfMemory,
_ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)),
}
})?;
// log::debug!("bias: {load_bias}");
let e = Self::load_elf_segment(
&mut user_vm,
param,
&seg_to_load,
vaddr + load_bias,
&elf_prot_flags,
&elf_map_flags,
total_size,
)
.map_err(|e| match e {
SystemError::EFAULT => ExecError::BadAddress(None),
SystemError::ENOMEM => ExecError::OutOfMemory,
_ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)),
})?;
// log::debug!("e.0={:?}", e.0);
// 如果地址不对,那么就报错
if !e.1 {
return Err(ExecError::BadAddress(Some(e.0)));
@ -754,12 +911,10 @@ impl BinaryLoader for ElfLoader {
if elf_type == ElfType::DSO {
// todo: 在这里增加对load_bias和reloc_func_desc的更新代码
load_bias += e.0.data()
- self
.elf_page_start(VirtAddr::new(
load_bias
+ TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
))
.data();
- Self::elf_page_start(VirtAddr::new(
load_bias + TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
))
.data();
_reloc_func_desc = load_bias;
}
}
@ -793,7 +948,7 @@ impl BinaryLoader for ElfLoader {
// 如果程序段要加载的目标地址不在用户空间内,或者是其他不合法的情况,那么就报错
if !p_vaddr.check_user()
|| seg_to_load.p_filesz > seg_to_load.p_memsz
|| self.elf_page_align_up(p_vaddr + seg_to_load.p_memsz as usize)
|| Self::elf_page_align_up(p_vaddr + seg_to_load.p_memsz as usize)
>= MMArch::USER_END_VADDR
{
// debug!("ERR: p_vaddr={p_vaddr:?}");
@ -801,7 +956,7 @@ impl BinaryLoader for ElfLoader {
}
// end vaddr of this segment(code+data+bss)
let seg_end_vaddr_f = self.elf_page_align_up(VirtAddr::new(
let seg_end_vaddr_f = Self::elf_page_align_up(VirtAddr::new(
(seg_to_load.p_vaddr + seg_to_load.p_filesz) as usize,
));
@ -839,7 +994,7 @@ impl BinaryLoader for ElfLoader {
end_code = end_code.map(|v| v + load_bias);
start_data = start_data.map(|v| v + load_bias);
end_data = end_data.map(|v| v + load_bias);
let mut interp_load_addr: Option<VirtAddr> = None;
// debug!(
// "to set brk: elf_bss: {:?}, elf_brk: {:?}, bss_prot_flags: {:?}",
// elf_bss,
@ -848,16 +1003,27 @@ impl BinaryLoader for ElfLoader {
// );
self.set_elf_brk(&mut user_vm, elf_bss, elf_brk, bss_prot_flags)?;
if likely(elf_bss != elf_brk) && unlikely(self.pad_zero(elf_bss).is_err()) {
if likely(elf_bss != elf_brk) && unlikely(Self::pad_zero(elf_bss).is_err()) {
// debug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}");
return Err(ExecError::BadAddress(Some(elf_bss)));
}
if interpreter.is_some() {
// TODO 添加对动态加载器的处理
drop(user_vm);
if let Some(mut interpreter) = interpreter {
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1249
let elf_entry = Self::load_elf_interp(&mut interpreter, load_bias)?.entry_point();
interp_load_addr = Some(elf_entry);
_reloc_func_desc = elf_entry.data();
//参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1269
//TODO allow_write_access(interpreter);
ProcessManager::current_pcb()
.fd_table()
.write()
.alloc_fd(interpreter.file(), None)
.map(|fd| fd as usize)
.map_err(|_| ExecError::InvalidParemeter)?;
}
// debug!("to create auxv");
let mut user_vm = binding.write();
self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?;
// debug!("auxv create ok");
@ -866,8 +1032,8 @@ impl BinaryLoader for ElfLoader {
user_vm.start_data = start_data.unwrap_or(VirtAddr::new(0));
user_vm.end_data = end_data.unwrap_or(VirtAddr::new(0));
let result = BinaryLoaderResult::new(program_entrypoint);
// debug!("elf load OK!!!");
let result = BinaryLoaderResult::new(interp_load_addr.unwrap_or(program_entrypoint));
// kdebug!("elf load OK!!!");
return Ok(result);
}
}

View File

@ -677,7 +677,7 @@ impl RobustListHead {
/// - head_uaddrrobust list head用户空间地址
/// - lenrobust list head的长度
pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
let robust_list_head_len = mem::size_of::<&RobustListHead>();
let robust_list_head_len = mem::size_of::<RobustListHead>();
if unlikely(len != robust_list_head_len) {
return Err(SystemError::EINVAL);
}

View File

@ -1,3 +1,5 @@
use crate::arch::rand::rand;
bitflags! {
pub struct GRandFlags: u8{
const GRND_NONBLOCK = 0x0001;
@ -6,6 +8,46 @@ bitflags! {
}
}
/// Generates an array of random bytes of size `N`.
///
/// This function fills an array of size `N` with random bytes by repeatedly
/// generating random numbers and converting them to little-endian byte arrays.
/// The function ensures that the entire array is filled with random bytes,
/// even if the size of the array is not a multiple of the size of `usize`.
///
/// # Type Parameters
///
/// * `N`: The size of the array to be filled with random bytes.
///
/// # Returns
///
/// An array of size `N` filled with random bytes.
///
/// # Example
///
/// ```rust
/// let random_bytes = rand_bytes::<16>();
/// assert_eq!(random_bytes.len(), 16);
/// ```
pub fn rand_bytes<const N: usize>() -> [u8; N] {
let mut bytes = [0u8; N];
let mut remaining = N;
let mut index = 0;
while remaining > 0 {
let random_num = rand();
let random_bytes = random_num.to_le_bytes();
let to_copy = core::cmp::min(remaining, size_of::<usize>());
bytes[index..index + to_copy].copy_from_slice(&random_bytes[..to_copy]);
index += to_copy;
remaining -= to_copy;
}
bytes
}
// 软件实现的随机数生成器
#[allow(dead_code)]
pub fn soft_rand() -> usize {

View File

@ -316,7 +316,6 @@ impl PageFaultHandler {
} else {
return VmFaultReason::VM_FAULT_OOM;
}
ret = ret.union(Self::finish_fault(pfm));
ret
@ -635,7 +634,9 @@ impl PageFaultHandler {
// TODO 同步预读
//涉及磁盘IO返回标志为VM_FAULT_MAJOR
ret = VmFaultReason::VM_FAULT_MAJOR;
let mut buffer = Box::new([0u8; MMArch::PAGE_SIZE]);
file.pread(
file_pgoff * MMArch::PAGE_SIZE,
MMArch::PAGE_SIZE,

View File

@ -251,7 +251,7 @@ impl From<VmFlags> for ProtFlags {
impl Syscall {
pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
// debug!("brk: new_addr={:?}", new_addr);
// log::debug!("brk: new_addr={:?}", new_addr);
let address_space = AddressSpace::current()?;
let mut address_space = address_space.write();
@ -263,6 +263,7 @@ impl Syscall {
}
unsafe {
// log::debug!("brk: set_brk new_addr={:?}", new_addr);
address_space
.set_brk(VirtAddr::new(page_align_up(new_addr.data())))
.ok();
@ -346,7 +347,6 @@ impl Syscall {
false,
)?
};
return Ok(start_page.virt_address().data());
}

View File

@ -38,7 +38,7 @@ pub enum AtType {
/// Frequency at which times() increments.
ClkTck,
/// Secure mode boolean.
Secure,
Secure = 23,
/// String identifying real platform, may differ from AT_PLATFORM.
BasePlatform,
/// Address of 16 random bytes.
@ -46,7 +46,7 @@ pub enum AtType {
/// Extension of AT_HWCAP.
HwCap2,
/// Filename of program.
ExecFn,
ExecFn = 31,
/// Minimal stack size for signal delivery.
MinSigStackSize,
}

View File

@ -157,6 +157,11 @@ impl ExecParam {
pub fn file_mut(&mut self) -> &mut File {
&mut self.file
}
/// 获取File的所有权用于将动态链接器加入文件描述符表中
pub fn file(self) -> File {
self.file
}
}
/// ## 加载二进制文件
@ -199,6 +204,7 @@ pub struct ProcInitInfo {
pub args: Vec<CString>,
pub envs: Vec<CString>,
pub auxv: BTreeMap<u8, usize>,
pub rand_num: [u8; 16],
}
impl ProcInitInfo {
@ -208,6 +214,7 @@ impl ProcInitInfo {
args: Vec::new(),
envs: Vec::new(),
auxv: BTreeMap::new(),
rand_num: [0u8; 16],
}
}
@ -218,7 +225,7 @@ impl ProcInitInfo {
///
/// 返回值是一个元组第一个元素是最终的用户栈顶地址第二个元素是环境变量pointer数组的起始地址
pub unsafe fn push_at(
&self,
&mut self,
ustack: &mut UserStack,
) -> Result<(VirtAddr, VirtAddr), SystemError> {
// 先把程序的名称压入栈中
@ -233,6 +240,7 @@ impl ProcInitInfo {
ustack.sp()
})
.collect::<Vec<_>>();
// 然后把参数压入栈中
let argps = self
.args
@ -243,6 +251,20 @@ impl ProcInitInfo {
})
.collect::<Vec<_>>();
// 压入随机数把指针放入auxv
self.push_slice(ustack, &[self.rand_num])?;
self.auxv
.insert(super::abi::AtType::Random as u8, ustack.sp().data());
// 实现栈的16字节对齐
// 用当前栈顶地址减去后续要压栈的长度得到的压栈后的栈顶地址与0xF按位与操作得到对齐要填充的字节数
let length_to_push = (self.auxv.len() + envps.len() + 1 + argps.len() + 1 + 1)
* core::mem::align_of::<usize>();
self.push_slice(
ustack,
&vec![0u8; (ustack.sp().data() - length_to_push) & 0xF],
)?;
// 压入auxv
self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
for (&k, &v) in self.auxv.iter() {
@ -256,7 +278,6 @@ impl ProcInitInfo {
// 把参数指针压入栈中
self.push_slice(ustack, &[null::<u8>()])?;
self.push_slice(ustack, argps.as_slice())?;
let argv_ptr = ustack.sp();
// 把argc压入栈中

View File

@ -1574,8 +1574,8 @@ pub struct KernelStack {
}
impl KernelStack {
pub const SIZE: usize = 0x4000;
pub const ALIGN: usize = 0x4000;
pub const SIZE: usize = 0x8000;
pub const ALIGN: usize = 0x8000;
pub fn new() -> Result<Self, SystemError> {
return Ok(Self {

View File

@ -25,6 +25,7 @@ use crate::{
procfs::procfs_register_pid,
vfs::{file::FileDescriptorVec, MAX_PATHLEN},
},
libs::rand::rand_bytes,
mm::{
ucontext::{AddressSpace, UserStack},
verify_area, MemoryManagementArch, VirtAddr,
@ -50,10 +51,10 @@ pub struct PosixOldUtsName {
impl PosixOldUtsName {
pub fn new() -> Self {
const SYS_NAME: &[u8] = b"DragonOS";
const SYS_NAME: &[u8] = b"Linux";
const NODENAME: &[u8] = b"DragonOS";
const RELEASE: &[u8] = env!("CARGO_PKG_VERSION").as_bytes();
const VERSION: &[u8] = env!("CARGO_PKG_VERSION").as_bytes();
const RELEASE: &[u8] = b"5.19.0";
const VERSION: &[u8] = b"5.19.0";
#[cfg(target_arch = "x86_64")]
const MACHINE: &[u8] = b"x86_64";
@ -176,6 +177,8 @@ impl Syscall {
// debug!("argv: {:?}, envp: {:?}", argv, envp);
param.init_info_mut().args = argv;
param.init_info_mut().envs = envp;
// // 生成16字节随机数
param.init_info_mut().rand_num = rand_bytes::<16>();
// 把proc_init_info写到用户栈上
let mut ustack_message = unsafe {
@ -187,7 +190,7 @@ impl Syscall {
};
let (user_sp, argv_ptr) = unsafe {
param
.init_info()
.init_info_mut()
.push_at(
// address_space
// .write()

View File

@ -30,7 +30,6 @@ use crate::{
filesystem::vfs::{
fcntl::{AtFlags, FcntlCommand},
file::FileMode,
stat::PosixKstat,
syscall::{ModeType, UtimensFlags},
MAX_PATHLEN,
},
@ -668,14 +667,7 @@ impl Syscall {
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
SYS_FSTAT => {
let fd = args[0] as i32;
let kstat: *mut PosixKstat = args[1] as *mut PosixKstat;
let vaddr = VirtAddr::new(kstat as usize);
// FIXME 由于c中的verify_area与rust中的verify_area重名所以在引入时加了前缀区分
// TODO 应该将用了c版本的verify_area都改为rust的verify_area
match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
Ok(_) => Self::fstat(fd, kstat),
Err(e) => Err(e),
}
Self::fstat(fd, args[1])
}
SYS_FCNTL => {
@ -778,15 +770,13 @@ impl Syscall {
#[cfg(target_arch = "x86_64")]
SYS_LSTAT => {
let path = args[0] as *const u8;
let kstat = args[1] as *mut PosixKstat;
Self::lstat(path, kstat)
Self::lstat(path, args[1])
}
#[cfg(target_arch = "x86_64")]
SYS_STAT => {
let path = args[0] as *const u8;
let kstat = args[1] as *mut PosixKstat;
Self::stat(path, kstat)
Self::stat(path, args[1])
}
SYS_STATFS => {
@ -902,8 +892,10 @@ impl Syscall {
}
SYS_EXIT_GROUP => {
warn!("SYS_EXIT_GROUP has not yet been implemented");
Ok(0)
let exit_code = args[0];
Self::exit(exit_code)
// warn!("SYS_EXIT_GROUP has not yet been implemented");
// Ok(0)
}
SYS_MADVISE => {
@ -1051,7 +1043,7 @@ impl Syscall {
SYS_RSEQ => {
warn!("SYS_RSEQ has not yet been implemented");
Ok(0)
Err(SystemError::ENOSYS)
}
#[cfg(target_arch = "x86_64")]

View File

@ -1 +1 @@
v1.11
v1.12

View File

@ -338,7 +338,7 @@ rustInstall
install_python_pkg
# 安装dadk
cargo install dadk || exit 1
cargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v0.4.0 || exit 1
bashpath=$(cd `dirname $0`; pwd)

View File

@ -1,6 +1,6 @@
docker rm -f dragonos-build || echo "No existed container"
cpu_count=$(cat /proc/cpuinfo |grep "processor"|wc -l)
docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.11 bash << EOF
docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.12 bash << EOF
source ~/.cargo/env
source ~/.bashrc
cd /data

View File

@ -79,6 +79,9 @@ $DADK -w $root_folder rootfs mount || exit 1
LOOP_DEVICE=$($DADK -w $root_folder rootfs show-loop-device || exit 1)
echo $LOOP_DEVICE
echo ${mount_folder}
FS_TYPE=$(findmnt -n -o FSTYPE ${mount_folder} || df -T ${mount_folder} | tail -1 | awk '{print $2}')
echo "FS_TYPE: $FS_TYPE"
# mkdir -p ${GRUB_INSTALL_PATH}
# 检测grub文件夹是否存在
@ -99,7 +102,12 @@ mkdir -p ${mount_folder}/bin
mkdir -p ${mount_folder}/dev
mkdir -p ${mount_folder}/proc
mkdir -p ${mount_folder}/usr
cp -r ${root_folder}/bin/sysroot/* ${mount_folder}/
if [ "$FS_TYPE" = "vfat" ] || [ "$FS_TYPE" = "fat32" ]; then
cp -rL ${root_folder}/bin/sysroot/* ${mount_folder}/
else
cp -r ${root_folder}/bin/sysroot/* ${mount_folder}/
fi
# 设置 grub 相关数据
if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then

View File

@ -2,7 +2,7 @@ user_sub_dirs = apps
DADK_VERSION=$(shell dadk -V | awk 'END {print $$2}')
# 最小的DADK版本
MIN_DADK_VERSION = 0.3.0
MIN_DADK_VERSION = 0.4.0
DADK_CACHE_DIR = $(ROOT_PATH)/bin/dadk_cache
ECHO:
@ -20,7 +20,7 @@ ifeq ("$(DADK_VERSION)", "")
@echo "\n\tcargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION)" --locked
@echo "\n"
@echo "Auto installing dadk..."
cargo install dadk
cargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION)" --locked
else
# 如果DADK版本过低则自动更新
@echo "dadk version $(DADK_VERSION) installed"

View File

@ -10,7 +10,7 @@ else
endif
ifeq ($(ARCH), x86_64)
export RUST_TARGET=x86_64-unknown-linux-musl
export RUST_TARGET=x86_64-unknown-linux-gnu
else ifeq ($(ARCH), riscv64)
export RUST_TARGET=riscv64gc-unknown-linux-gnu
else

View File

@ -1,5 +1,5 @@
ifeq ($(ARCH), x86_64)
CROSS_COMPILE=x86_64-linux-musl-
CROSS_COMPILE=x86_64-linux-gnu-
else ifeq ($(ARCH), riscv64)
CROSS_COMPILE=riscv64-linux-musl-
endif
@ -8,7 +8,7 @@ CC=$(CROSS_COMPILE)gcc
.PHONY: all
all: main.c
$(CC) -static -o test_fstat main.c
$(CC) -o test_fstat main.c
.PHONY: install clean
install: all

View File

@ -1,5 +1,5 @@
ifeq ($(ARCH), x86_64)
CROSS_COMPILE=x86_64-linux-musl-
CROSS_COMPILE=x86_64-linux-gnu-
else ifeq ($(ARCH), riscv64)
CROSS_COMPILE=riscv64-linux-musl-
endif
@ -8,7 +8,7 @@ CC=$(CROSS_COMPILE)gcc
.PHONY: all
all: main.c
$(CC) -static -o test_newfstatat main.c
$(CC) -o test_newfstatat main.c
.PHONY: install clean
install: all

View File

@ -22,6 +22,10 @@ type = "build-from-source"
source = "archive"
# 路径或URL
source-path = "https://mirrors.dragonos.org.cn/pub/third_party/gnu/coreutils/coreutils-9.4.tar.xz"
# 把压缩包中的哪个目录作为根目录(可选),仅当 source = "archive" 时生效
archive-rootdir = "coreutils-9.4"
# 构建相关信息
[build]
# (可选)构建命令

View File

@ -0,0 +1,40 @@
# 用户程序名称
name = "glibc_bin_ubuntu2404"
# 版本号
version = "2.39"
# 用户程序描述信息
description = "GNU C Library for Ubuntu 24.04"
# (可选)默认: false 是否只构建一次如果为trueDADK会在构建成功后将构建结果缓存起来下次构建时直接使用缓存的构建结果
build-once = false
# (可选) 默认: false 是否只安装一次如果为trueDADK会在安装成功后不再重复安装
install-once = false
# 目标架构
# 可选值:"x86_64", "aarch64", "riscv64", "loongarch64"
target-arch = ["x86_64"]
# 任务源
[task-source]
# 构建类型
# 可选值:"build-from-source", "install-from-prebuilt"
type = "install-from-prebuilt"
# 构建来源
# "build_from_source" 可选值:"git", "local", "archive"
# "install_from_prebuilt" 可选值:"local", "archive"
source = "archive"
# 路径或URL
source-path = "https://mirrors.dragonos.org.cn/pub/third_party/gnu/glibc-bin/glibc-ubuntu2404-x86_64-202505111756-8f3207567bf10f4d09027b2cd84b7807.tar.xz"
archive-rootdir = "sysroot/"
[build]
# 安装相关信息
[install]
# 可选安装到DragonOS的路径
in-dragonos-path = "/"
# 清除相关信息
[clean]
# (可选)清除命令
clean-command = ""
# (可选)依赖项
# 注意:如果没有依赖项,忽略此项,不允许只留一个[[depends]]
# (可选)环境变量
# 注意:如果没有环境变量,忽略此项,不允许只留一个[[envs]]

View File

@ -22,10 +22,13 @@ type = "build-from-source"
source = "archive"
# 路径或URL
source-path = "https://mirrors.dragonos.org.cn/pub/third_party/musl/musl-1.2.4.tar.gz"
# 把压缩包中的哪个目录作为根目录(可选),仅当 source = "archive" 时生效
archive-rootdir = "musl-1.2.4"
# 构建相关信息
[build]
# (可选)构建命令
build-command = "touch config.mak && DESTDIR=$DADK_CURRENT_BUILD_DIR make install -j $(nproc)"
build-command = "touch config.mak && DESTDIR=$DADK_CURRENT_BUILD_DIR make install -j $(nproc) && rm -rf $DADK_CURRENT_BUILD_DIR/lib && rm -rf $DADK_CURRENT_BUILD_DIR/lib64"
# 安装相关信息
[install]
# 可选安装到DragonOS的路径

View File

@ -8,3 +8,4 @@ Restart=always
ExecStartPre=-/bin/about.elf
ExecStartPre=/bin/busybox stty erase 127
Environment=PATH=/bin:/usr/bin:/usr/local/bin
Environment=LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib