On Sat, Aug 19, 2023 at 3:49 AM Karim Taha <kariem.taha...@gmail.com> wrote:
> From: Stacey Son <s...@freebsd.org> > > Co-authored-by: Mikaël Urankar <mikael.uran...@gmail.com> > > Signed-off-by: Mikaël Urankar <mikael.uran...@gmail.com> > Signed-off-by: Stacey Son <s...@freebsd.org> > Signed-off-by: Karim Taha <kariem.taha...@gmail.com> > --- > bsd-user/bsd-mem.h | 85 +++++++++++++++++++++++++++++++++++ > bsd-user/freebsd/os-syscall.c | 7 +++ > 2 files changed, 92 insertions(+) > emacs works with this, iirc, and it's super picky about brk being pedantically correct. This also doesn't match current linux-user. Perhaps the caution it uses is no longer needed? I think it's another area we should invite the linux-user maintainers to comment. Warner > diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h > index edbccd3111..6f33148eb7 100644 > --- a/bsd-user/bsd-mem.h > +++ b/bsd-user/bsd-mem.h > @@ -167,4 +167,89 @@ static inline abi_long do_bsd_mincore(abi_ulong > target_addr, abi_ulong len, > return ret; > } > > +#ifdef DO_DEBUG > +#define DEBUGF_BRK(message, args...) \ > + do { fprintf(stderr, (message), ## args); } while (0) > +#else > +#define DEBUGF_BRK(message, args...) > +#endif > + > +/* do_brk() must return target values and target errnos. */ > +static inline abi_long do_obreak(abi_ulong new_brk) > +{ > + abi_long mapped_addr; > + int new_alloc_size; > + > + DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk); > + > + if (!new_brk) { > + DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", bsd_target_brk); > + return bsd_target_brk; > + } > + if (new_brk < bsd_target_original_brk) { > + DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < > bsd_target_original_brk)\n", > + bsd_target_brk); > + return bsd_target_brk; > + } > + > + /* > + * If the new brk is less than the highest page reserved to the > target heap > + * allocation, set it and we're almost done... > + */ > + if (new_brk <= brk_page) { > + /* > + * Heap contents are initialized to zero, as for anonymous mapped > pages. > + */ > + if (new_brk > bsd_target_brk) { > + memset(g2h_untagged(bsd_target_brk), 0, new_brk - > bsd_target_brk); > + } > + bsd_target_brk = new_brk; > + DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", > + bsd_target_brk); > + return bsd_target_brk; > + } > + > + /* > + * We need to allocate more memory after the brk... Note that we > don't use > + * MAP_FIXED because that will map over the top of any existing > mapping > + * (like the one with the host libc or qemu itself); instead we treat > + * "mapped but at wrong address" as a failure and unmap again. > + */ > + new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page); > + mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, > + PROT_READ | PROT_WRITE, > + MAP_ANON | MAP_PRIVATE, -1, 0)); > + > + if (mapped_addr == brk_page) { > + /* > + * Heap contents are initialized to zero, as for anonymous mapped > pages. > + * Technically the new pages are already initialized to zero > since they > + * *are* anonymous mapped pages, however we have to take care > with the > + * contents that come from the remaining part of the previous > page: it > + * may contains garbage data due to a previous heap usage (grown > then > + * shrunken). > + */ > + memset(g2h_untagged(bsd_target_brk), 0, brk_page - > bsd_target_brk); > + > + bsd_target_brk = new_brk; > + brk_page = HOST_PAGE_ALIGN(bsd_target_brk); > + DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n", > + bsd_target_brk); > + return bsd_target_brk; > + } else if (mapped_addr != -1) { > + /* > + * Mapped but at wrong address, meaning there wasn't actually > enough > + * space for this brk. > + */ > + target_munmap(mapped_addr, new_alloc_size); > + mapped_addr = -1; > + DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", > bsd_target_brk); > + } else { > + DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", bsd_target_brk); > + } > + > + /* For everything else, return the previous break. */ > + return bsd_target_brk; > +} > + > #endif /* BSD_USER_BSD_MEM_H */ > diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c > index 1db0907504..1b9dca9164 100644 > --- a/bsd-user/freebsd/os-syscall.c > +++ b/bsd-user/freebsd/os-syscall.c > @@ -543,6 +543,13 @@ static abi_long freebsd_syscall(void *cpu_env, int > num, abi_long arg1, > break; > #endif > > + /* > + * Misc > + */ > + case TARGET_FREEBSD_NR_break: > + ret = do_obreak(arg1); > + break; > + > /* > * sys{ctl, arch, call} > */ > -- > 2.40.0 > >