Re: [PATCH] Fix const pointer assignment trick on clang 9+

2021-10-08 Thread 余生与君
Tried, not working.

On Fri, Oct 8, 2021 at 10:21 PM Denys Vlasenko  wrote:
>
> On Fri, Oct 8, 2021 at 10:39 AM 余生与君  wrote:
> > On Thu, Oct 7, 2021 at 9:48 PM Denys Vlasenko  
> > wrote:
> > > Can you try something more? E.g. (in current git):
> > >
> > > #define ASSIGN_CONST_PTR(p, v) do { \
> > > *(void**)not_const_pp() = (void*)(v); \
> > > /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
> > > barrier(); \
> > > +   sleep(0); \
> > > } while (0)
> >
> > Cool! Sleep(0) does the magic!
> >
> > ADRPX21, #ash_ptr_to_globals_misc_ptr@PAGE
> > LDR X21, [X21,#ash_ptr_to_globals_misc_ptr@PAGEOFF]
> > MOV X8, X21
> > STR X0, [X8]
> > MOV W0, WZR
> > BL  sleep
> > LDR X21, [X21]
> >
> >
> > And further investigation shows that a dummy function can also do this 
> > trick!
> >
> > hack.c:
> > void clang_barrier() {
> > }
>
> We don't need the function call. We only need to tell clang that
> a lot of registers are "needed" for something.
> This "something" ideally should be nothing.
>
> Can you try this?
>
> #if defined(__clang_major__) && __clang_major__ >= 9
> /* Clang/llvm drops assignment to "constant" storage. Silently.
>  * Needs serious convincing to not eliminate the store.
>  */
> static ALWAYS_INLINE void register_barrier(void)
> {
> int r0, r1, r2, r3, r4, r5;
> asm volatile (
> "# clobber 6 registers"
> : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(r4), "=r"(r5)
> : "0"(r1), "1"(r1), "2"(r2), "3"(r3), "4"(r4), "5"(r5)
> : "memory"
>
> );
> }
> static ALWAYS_INLINE void* not_const_pp(const void *p)
> {
> void *pp;
> asm volatile (
> "# forget that p points to const"
> : /*outputs*/ "=r" (pp)
> : /*inputs*/ "0" (p)
> );
> return pp;
> }
> #define ASSIGN_CONST_PTR(p, v) do { \
> *(void**)not_const_pp() = (void*)(v); \
> register_barrier();
> } while (0)
> #else
> static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; }
> #define ASSIGN_CONST_PTR(p, v) do { \
> *(void**)not_const_pp() = (void*)(v); \
> /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
> barrier(); \
> } while (0)
> #endif
>
> If this works, experiment what minimum number of rN
> in register_barrier() is actually needed to placate clang.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] Fix const pointer assignment trick on clang 9+

2021-10-08 Thread 余生与君
Tried. Not working.

On Fri, Oct 8, 2021 at 10:35 PM Henrique de Moraes Holschuh
 wrote:
>
> On 08/10/2021 05:39, 余生与君 wrote:
> > And further investigation shows that a dummy function can also do this 
> > trick!
>
> When one wants any sort of barrier (compiler optimization barrier, CPU
> execution barrier, memory barriers, etc) that works (and is also
> extremely likely to remain working in the future) for both GCC and
> CLANG, it is usually a good idea to take a look at what the linux kernel
> is using.
>
>
> --8<-- from include/linux/compiler.h (latest linux kernel source)
>
> /* Optimization barrier */
> #ifndef barrier
> /* The "volatile" is due to gcc bugs */
> # define barrier() __asm__ __volatile__("": : :"memory")
> #endif
>
> #ifndef barrier_data
> /*
> * This version is i.e. to prevent dead stores elimination on @ptr
> * where gcc and llvm may behave differently when otherwise using
> * normal barrier(): while gcc behavior gets along with a normal
> * barrier(), llvm needs an explicit input variable to be assumed
> * clobbered. The issue is as follows: while the inline asm might
> * access any memory it wants, the compiler could have fit all of
> * @ptr into memory registers instead, and since @ptr never escaped
> * from that, it proved that the inline asm wasn't touching any of
> * it. This version works well with both compilers, i.e. we're telling
> * the compiler that the inline asm absolutely may see the contents
> * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
> */
> # define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
> #endif
>
> --8<--
>
> --
> Henrique de Moraes Holschuh
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] ash: improve speed of variable pattern substitution

2021-10-08 Thread Denys Vlasenko
On Wed, Jul 21, 2021 at 10:54 PM Alin Mr  wrote:
>
> Ron, thanks for your quick patch and the hints. I saw your message and was 
> thinking through;  fixed-length patterns don't need backtracking. '?' 
> (without '*') also results in fixed-length patterns, so maybe that'd be more 
> complicated to detect.
>
> To motivate this a bit: it started with quoters. Since we have neither bash's 
> ${x@Q}, nor `printf %q`, it's harder to escape shell code for eval, or to 
> produce quoted SQL values **efficiently**.

A patch to implement e.g. ${x@Q} is acceptable.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] ash.c: speedup ${s:} substring (no quotes)

2021-10-08 Thread Denys Vlasenko
On Wed, Jul 28, 2021 at 10:40 AM Alin Mr  wrote:
> This trivial patch makes ${s:...} at least as fast as ${s#??..} in
> simple tests. It's probably faster for longer substrings, but then one
> wouldn't use ${s#"1024???s"} anyway -- one would switch away from sh.
> memmove could possibly be replaced by memcpy.
>
> I haven't found much on testing (or contributing for that matter) on the
> website or in the source. `make test` produces a bunch of failures on
> master anyway, so I'm not sure how to test new code.

cd shell/ash_test

./run-all


> Signed-off-by: Alin Mr 
> ---
>   shell/ash.c | 23 +--
>   1 file changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/shell/ash.c b/shell/ash.c
> index b5947147a..df4d82e39 100644
> --- a/shell/ash.c
> +++ b/shell/ash.c
> @@ -7198,14 +7198,25 @@ subevalvar(char *start, char *str, int strloc,
> if ((unsigned)len > (orig_len - pos))
> len = orig_len - pos;
>
> -   for (vstr = startp; pos; vstr++, pos--) {
> -   if (quotes && (unsigned char)*vstr == CTLESC)
> -   vstr++;
> +   if (! quotes) {
> +   vstr = startp + pos;
> +   pos = 0;

"pos = 0" is useless

> +   } else {
> +   for (vstr = startp; pos; vstr++, pos--) {
> +   if ((unsigned char)*vstr == CTLESC)
> +   vstr++;
> +   }
> }
> -   for (loc = startp; len; len--) {
> -   if (quotes && (unsigned char)*vstr == CTLESC)
> +   if (! quotes) {

You can also merge if (!quotes) {} blocks - why test the condition twice?

> +   memmove (loc, vstr, len);

Should be memmove(startp, vstr, len).

> +   loc = startp + len;
> +   len = 0;

"len = 0" is useless.

> +   } else {
> +   for (loc = startp; len; len--) {
> +   if ((unsigned char)*vstr == CTLESC)
> +   *loc++ = *vstr++;
> *loc++ = *vstr++;
> -   *loc++ = *vstr++;
> +   }
> }
> *loc = '\0';
> goto out;

Applied in this form:

if (!quotes) {
loc = mempcpy(startp, startp + pos, len);
} else {
for (vstr = startp; pos != 0; pos--) {
if ((unsigned char)*vstr == CTLESC)
vstr++;
vstr++;
}
for (loc = startp; len != 0; len--) {
if ((unsigned char)*vstr == CTLESC)
*loc++ = *vstr++;
*loc++ = *vstr++;
}
}

Thank you.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] libbb: better coreutils compatibility for realpath

2021-10-08 Thread Denys Vlasenko
Applied, thanks.

On Sat, Jul 31, 2021 at 2:52 PM Ron Yorston  wrote:
>
> Add some tests which coreutils realpath pass but BusyBox realpath
> fails (bar one).  Adjust xmalloc_realpath_coreutils() so the tests
> pass:
>
> - Expand symbolic links before testing whether the last path component
>   exists.
>
> - When the link target is a relative path canonicalize it by passing
>   it through xmalloc_realpath_coreutils() as already happens for
>   absolute paths.
>
> - Ignore trailing slashes when finding the last path component and
>   correctly handle the case where the only slash is at the start of
>   the path.  This requires ignoring superfluous leading slashes.
>
> - Undo all changes to the path so error messages from the caller show
>   the original filename.
>
> function old new   delta
> xmalloc_realpath_coreutils   214 313 +99
>
> Signed-off-by: Ron Yorston 
> ---
>  include/libbb.h  |  2 +-
>  libbb/xreadlink.c| 75 
>  testsuite/realpath.tests | 45 
>  3 files changed, 91 insertions(+), 31 deletions(-)
>  create mode 100755 testsuite/realpath.tests
>
> diff --git a/include/libbb.h b/include/libbb.h
> index 7d6ab4a93..3c9ed792e 100644
> --- a/include/libbb.h
> +++ b/include/libbb.h
> @@ -561,7 +561,7 @@ DIR *xopendir(const char *path) FAST_FUNC;
>  DIR *warn_opendir(const char *path) FAST_FUNC;
>
>  char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC;
> -char *xmalloc_realpath_coreutils(const char *path) FAST_FUNC RETURNS_MALLOC;
> +char *xmalloc_realpath_coreutils(char *path) FAST_FUNC RETURNS_MALLOC;
>  char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC;
>  char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC;
>  /* !RETURNS_MALLOC: it's a realloc-like function */
> diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
> index a18dd0748..2682f6975 100644
> --- a/libbb/xreadlink.c
> +++ b/libbb/xreadlink.c
> @@ -123,7 +123,7 @@ char* FAST_FUNC xmalloc_realpath(const char *path)
>  #endif
>  }
>
> -char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
> +char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
>  {
> char *buf;
>
> @@ -137,32 +137,19 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char 
> *path)
>  * (the directory must exist).
>  */
> if (!buf && errno == ENOENT) {
> -   char *last_slash = strrchr(path, '/');
> -   if (last_slash) {
> -   *last_slash++ = '\0';
> -   buf = xmalloc_realpath(path);
> -   if (buf) {
> -   unsigned len = strlen(buf);
> -   buf = xrealloc(buf, len + strlen(last_slash) 
> + 2);
> -   buf[len++] = '/';
> -   strcpy(buf + len, last_slash);
> -   }
> -   } else {
> -   char *target = xmalloc_readlink(path);
> -   if (target) {
> -   char *cwd;
> -   if (target[0] == '/') {
> -   /*
> -* $ ln -s /bin/qwe symlink  # note: 
> /bin is a link to /usr/bin
> -* $ readlink -f symlink
> -* /usr/bin/qwe/target_does_not_exist
> -* $ realpath symlink
> -* /usr/bin/qwe/target_does_not_exist
> -*/
> -   buf = 
> xmalloc_realpath_coreutils(target);
> -   free(target);
> -   return buf;
> -   }
> +   char *target, c, *last_slash;
> +   size_t i;
> +
> +   target = xmalloc_readlink(path);
> +   if (target) {
> +   /*
> +* $ ln -s /bin/qwe symlink  # note: /bin is a link 
> to /usr/bin
> +* $ readlink -f symlink
> +* /usr/bin/qwe
> +* $ realpath symlink
> +* /usr/bin/qwe
> +*/
> +   if (target[0] != '/') {
> /*
>  * $ ln -s target_does_not_exist symlink
>  * $ readlink -f symlink
> @@ -170,13 +157,41 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char 
> *path)
>  * $ realpath symlink
>  * /CURDIR/target_does_not_exist
>  */
> -   cwd = 

Re: [PATCH v2 1/1] mktemp: add tmpdir option

2021-10-08 Thread Denys Vlasenko
Applied, thanks

On Fri, Jun 25, 2021 at 8:01 AM Andrej Valek  wrote:
>
> Make mktemp more compatible with coreutils.
> - add "--tmpdir" option
> - add long variants for "d,q,u" options
>
> Note: Upstream ca-certificate update script started using this option.
>
> Signed-off-by: Andrej Valek 
> Signed-off-by: Peter Marko 
> ---
>  coreutils/mktemp.c | 26 ++
>  1 file changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c
> index 5393320a5..05c6d98c6 100644
> --- a/coreutils/mktemp.c
> +++ b/coreutils/mktemp.c
> @@ -39,16 +39,17 @@
>  //kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
>
>  //usage:#define mktemp_trivial_usage
> -//usage:   "[-dt] [-p DIR] [TEMPLATE]"
> +//usage:   "[-dt] [-p DIR, --tmpdir[=DIR]] [TEMPLATE]"
>  //usage:#define mktemp_full_usage "\n\n"
>  //usage:   "Create a temporary file with name based on TEMPLATE and 
> print its name.\n"
>  //usage:   "TEMPLATE must end with XX (e.g. [/dir/]nameXX).\n"
>  //usage:   "Without TEMPLATE, -t tmp.XX is assumed.\n"
> -//usage: "\n   -d  Make directory, not file"
> -//usage: "\n   -q  Fail silently on errors"
> -//usage: "\n   -t  Prepend base directory name to TEMPLATE"
> -//usage: "\n   -p DIR  Use DIR as a base directory (implies -t)"
> -//usage: "\n   -u  Do not create anything; print a name"
> +//usage: "\n   -d  Make directory, not file"
> +//usage: "\n   -q  Fail silently on errors"
> +//usage: "\n   -t  Prepend base directory name 
> to TEMPLATE"
> +//usage: "\n   -p DIR, --tmpdir[=DIR]  Use DIR as a base directory 
> (implies -t)"
> +//usage: "\n   For --tmpdir is a optional 
> one."
> +//usage: "\n   -u  Do not create anything; print 
> a name"
>  //usage: "\n"
>  //usage: "\nBase directory is: -p DIR, else $TMPDIR, else /tmp"
>  //usage:
> @@ -72,13 +73,22 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
> OPT_t = 1 << 2,
> OPT_p = 1 << 3,
> OPT_u = 1 << 4,
> +   OPT_td = 1 << 5,
> };
>
> path = getenv("TMPDIR");
> if (!path || path[0] == '\0')
> path = "/tmp";
>
> -   opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, );
> +   opts = getopt32long(argv, "^"
> +  "dqtp:u\0"
> +  "?1" /* 1 arg max */,
> +  "directory\0" No_argument   "d"
> +  "quiet\0" No_argument   "q"
> +  "dry-run\0"   No_argument   "u"
> +  "tmpdir\0"Optional_argument "\xff"
> +  , , 
> +   );
>
> chp = argv[optind];
> if (!chp) {
> @@ -95,7 +105,7 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
> goto error;
> }
>  #endif
> -   if (opts & (OPT_t|OPT_p))
> +   if (opts & (OPT_t|OPT_p|OPT_td))
> chp = concat_path_file(path, chp);
>
> if (opts & OPT_u) {
> --
> 2.11.0
>
> ___
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] Fix const pointer assignment trick on clang 9+

2021-10-08 Thread Henrique de Moraes Holschuh

On 08/10/2021 05:39, 余生与君 wrote:

And further investigation shows that a dummy function can also do this trick!


When one wants any sort of barrier (compiler optimization barrier, CPU 
execution barrier, memory barriers, etc) that works (and is also 
extremely likely to remain working in the future) for both GCC and 
CLANG, it is usually a good idea to take a look at what the linux kernel 
is using.



--8<-- from include/linux/compiler.h (latest linux kernel source)

/* Optimization barrier */
#ifndef barrier
/* The "volatile" is due to gcc bugs */
# define barrier() __asm__ __volatile__("": : :"memory")
#endif

#ifndef barrier_data
/*
* This version is i.e. to prevent dead stores elimination on @ptr
* where gcc and llvm may behave differently when otherwise using
* normal barrier(): while gcc behavior gets along with a normal
* barrier(), llvm needs an explicit input variable to be assumed
* clobbered. The issue is as follows: while the inline asm might
* access any memory it wants, the compiler could have fit all of
* @ptr into memory registers instead, and since @ptr never escaped
* from that, it proved that the inline asm wasn't touching any of
* it. This version works well with both compilers, i.e. we're telling
* the compiler that the inline asm absolutely may see the contents
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
*/
# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
#endif

--8<--

--
Henrique de Moraes Holschuh
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: devmem: use mmap64 replace mmap

2021-10-08 Thread Ismael Luceno
On 08/Oct/2021 16:45, Denys Vlasenko wrote:
> On Fri, Oct 8, 2021 at 10:16 AM xiechengliang  
> wrote:
> >
> > I have built busybox with CONFIG_LFS=y, this problem still exists.
> >
> > mmap is defined in glibc as below:
> > void *mmap(void *addr, size_t len, int prot , int flags , int fd, off_t 
> > offset);
> > The type of last parameter offset is off_ t, so using mmap will still cause 
> > truncation problems.
> 
> 
> With CONFIG_LFS=y, off_t should be (at least) 64-bit.
> 
> Tell me more about the architecture you are building for.
> Is it bionic, maybe? They had some weird cases where off_t stays 32-bit.

Looks like it could be bionic. At least none of:
- glibc
- uclibc
- uclibc-ng
- musl

Targeting anything earlier than Android NDK API 21 probably will not work
without workarounds.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: httpd ranges do not work over 4gb

2021-10-08 Thread Lauri Kasanen
On Fri, 8 Oct 2021 15:58:47 +0200
Denys Vlasenko  wrote:

> WRONG. If CONFIG_LFS is off, sizeof(off_t) can be larger than sizeof(int).
> x86_64 is an example.
>
>
> Fixed in git, please test.

Fixed! Thanks.

- Lauri
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Redirection of stdout for commands

2021-10-08 Thread sleepy_dog




Denys Vlasenko wrote:
> [busybox] dd --help prints to stderr.

D'oh! Lol, thanks!
Any particular reason for this choice? It seems unintuitive to me to put
normal output on an error stream, I guess separation of busybox itself
and commands was wanted for some reason?




On Fri, Oct 8, 2021 at 4:15 PM  wrote:

Hello there,

1st time post here.

On a BusyBox based system (image built recently) I have a program
calling external executables and reading their text output.
This is done with fork, execl, and beforehand, redirecting the output
with dup2, quite like here:
https://dzone.com/articles/simple-popen2-implementation

This generally works. There is one oddity, when calling Linux commands
with this method:

Depending on whether I run that same program on a regular distribution
Linux machine, or on BusyBox, I get different results.
It works as expected on e.g. Ubuntu.
On BusyBox, it's different:
- if I call only BusyBox with "busybox --help", rhings work as expected,
e.g. nothing spills to the console, and I read all the input vie my
redirected stdout

busybox --help prints to stdout.


- if I call a command handle by busybox, e.g. "dd --help", I get back
nothing from stdout, and all text output spills directly on the console
- if I call busybox explicitly, with the command added, like "busybox dd
--help", it's the same as previous, i.e. doesn't work

[busybox] dd --help prints to stderr.



___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: devmem: use mmap64 replace mmap

2021-10-08 Thread Denys Vlasenko
On Fri, Oct 8, 2021 at 10:16 AM xiechengliang  wrote:
>
> I have built busybox with CONFIG_LFS=y, this problem still exists.
>
> mmap is defined in glibc as below:
> void *mmap(void *addr, size_t len, int prot , int flags , int fd, off_t 
> offset);
> The type of last parameter offset is off_ t, so using mmap will still cause 
> truncation problems.


With CONFIG_LFS=y, off_t should be (at least) 64-bit.

Tell me more about the architecture you are building for.
Is it bionic, maybe? They had some weird cases where off_t stays 32-bit.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Redirection of stdout for commands

2021-10-08 Thread Denys Vlasenko
On Fri, Oct 8, 2021 at 4:15 PM  wrote:
> Hello there,
>
> 1st time post here.
>
> On a BusyBox based system (image built recently) I have a program
> calling external executables and reading their text output.
> This is done with fork, execl, and beforehand, redirecting the output
> with dup2, quite like here:
> https://dzone.com/articles/simple-popen2-implementation
>
> This generally works. There is one oddity, when calling Linux commands
> with this method:
>
> Depending on whether I run that same program on a regular distribution
> Linux machine, or on BusyBox, I get different results.
> It works as expected on e.g. Ubuntu.
> On BusyBox, it's different:
> - if I call only BusyBox with "busybox --help", rhings work as expected,
> e.g. nothing spills to the console, and I read all the input vie my
> redirected stdout

busybox --help prints to stdout.

> - if I call a command handle by busybox, e.g. "dd --help", I get back
> nothing from stdout, and all text output spills directly on the console
> - if I call busybox explicitly, with the command added, like "busybox dd
> --help", it's the same as previous, i.e. doesn't work

[busybox] dd --help prints to stderr.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] Fix const pointer assignment trick on clang 9+

2021-10-08 Thread Denys Vlasenko
On Fri, Oct 8, 2021 at 4:21 PM Denys Vlasenko  wrote:
> Can you try this?
>
> #if defined(__clang_major__) && __clang_major__ >= 9
> /* Clang/llvm drops assignment to "constant" storage. Silently.
>  * Needs serious convincing to not eliminate the store.
>  */
> static ALWAYS_INLINE void register_barrier(void)
> {
> int r0, r1, r2, r3, r4, r5;
> asm volatile (
> "# clobber 6 registers"
> : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(r4), "=r"(r5)
> : "0"(r1), "1"(r1), "2"(r2), "3"(r3), "4"(r4), "5"(r5)
> : "memory"
>
> );
> }

should be "0"(r0), not r1; also, dummy-initialize them to avoid warnings:

static ALWAYS_INLINE void register_barrier(void)
{
int r0 = r0, r1 = r1, r2 = r2, r3 = r3, r4 = r4, r5 = r5;
asm volatile (
"# clobber 6 registers"
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(r4), "=r"(r5)
: "0"(r0), "1"(r1), "2"(r2), "3"(r3), "4"(r4), "5"(r5)
: "memory"
);
}

6 registers is maximum what does not fail to compile for i386.
Size growth +1021 bytes.

5 registers: +564 bytes
4 registers: +424 bytes
3 registers: +303 bytes
2 registers: +205 bytes
1 register: +101 bytes
0 registers: 0 bytes (as expected)
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] Fix const pointer assignment trick on clang 9+

2021-10-08 Thread Denys Vlasenko
On Fri, Oct 8, 2021 at 10:39 AM 余生与君  wrote:
> On Thu, Oct 7, 2021 at 9:48 PM Denys Vlasenko  
> wrote:
> > Can you try something more? E.g. (in current git):
> >
> > #define ASSIGN_CONST_PTR(p, v) do { \
> > *(void**)not_const_pp() = (void*)(v); \
> > /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
> > barrier(); \
> > +   sleep(0); \
> > } while (0)
>
> Cool! Sleep(0) does the magic!
>
> ADRPX21, #ash_ptr_to_globals_misc_ptr@PAGE
> LDR X21, [X21,#ash_ptr_to_globals_misc_ptr@PAGEOFF]
> MOV X8, X21
> STR X0, [X8]
> MOV W0, WZR
> BL  sleep
> LDR X21, [X21]
>
>
> And further investigation shows that a dummy function can also do this trick!
>
> hack.c:
> void clang_barrier() {
> }

We don't need the function call. We only need to tell clang that
a lot of registers are "needed" for something.
This "something" ideally should be nothing.

Can you try this?

#if defined(__clang_major__) && __clang_major__ >= 9
/* Clang/llvm drops assignment to "constant" storage. Silently.
 * Needs serious convincing to not eliminate the store.
 */
static ALWAYS_INLINE void register_barrier(void)
{
int r0, r1, r2, r3, r4, r5;
asm volatile (
"# clobber 6 registers"
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(r4), "=r"(r5)
: "0"(r1), "1"(r1), "2"(r2), "3"(r3), "4"(r4), "5"(r5)
: "memory"

);
}
static ALWAYS_INLINE void* not_const_pp(const void *p)
{
void *pp;
asm volatile (
"# forget that p points to const"
: /*outputs*/ "=r" (pp)
: /*inputs*/ "0" (p)
);
return pp;
}
#define ASSIGN_CONST_PTR(p, v) do { \
*(void**)not_const_pp() = (void*)(v); \
register_barrier();
} while (0)
#else
static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; }
#define ASSIGN_CONST_PTR(p, v) do { \
*(void**)not_const_pp() = (void*)(v); \
/* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
barrier(); \
} while (0)
#endif

If this works, experiment what minimum number of rN
in register_barrier() is actually needed to placate clang.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Redirection of stdout for commands

2021-10-08 Thread sleepy_dog

Hello there,

1st time post here.

On a BusyBox based system (image built recently) I have a program
calling external executables and reading their text output.
This is done with fork, execl, and beforehand, redirecting the output
with dup2, quite like here:
https://dzone.com/articles/simple-popen2-implementation

This generally works. There is one oddity, when calling Linux commands
with this method:

Depending on whether I run that same program on a regular distribution
Linux machine, or on BusyBox, I get different results.
It works as expected on e.g. Ubuntu.
On BusyBox, it's different:
- if I call only BusyBox with "busybox --help", rhings work as expected,
e.g. nothing spills to the console, and I read all the input vie my
redirected stdout
- if I call a command handle by busybox, e.g. "dd --help", I get back
nothing from stdout, and all text output spills directly on the console
- if I call busybox explicitly, with the command added, like "busybox dd
--help", it's the same as previous, i.e. doesn't work

Why is this, and can I make it work?

Thanks,
- Steve

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: httpd ranges do not work over 4gb

2021-10-08 Thread Denys Vlasenko
On Fri, Oct 8, 2021 at 2:45 PM Lauri Kasanen  wrote:
>
> Hi,
>
> On current bb master httpd, when the client requests valid Range: bytes
> over 4gb, the response is wrong - it sends the entire file instead of
> the requested range.
>
> E.g.
> Range: bytes=5926192128-5926195199
>
> This is on x86_64, so CONFIG_LFS etc shouldn't matter. I haven't
> yet looked deeper if it's just a matter of using 64-bit vars.

Bug in libbb.h:

#else
/* CONFIG_LFS is off */
# if UINT_MAX == 0x
/* While sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway.
 * gcc will throw warnings on printf("%d", off_t). Crap... */
typedef unsigned long uoff_t;
#  define XATOOFF(a) xatoi_positive(a)
#  define BB_STRTOOFF bb_strtou
#  define STRTOOFF strtol
#  define OFF_FMT "l"

WRONG. If CONFIG_LFS is off, sizeof(off_t) can be larger than sizeof(int).
x86_64 is an example.


Fixed in git, please test.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


httpd ranges do not work over 4gb

2021-10-08 Thread Lauri Kasanen
Hi,

On current bb master httpd, when the client requests valid Range: bytes
over 4gb, the response is wrong - it sends the entire file instead of
the requested range.

E.g.
Range: bytes=5926192128-5926195199

This is on x86_64, so CONFIG_LFS etc shouldn't matter. I haven't
yet looked deeper if it's just a matter of using 64-bit vars.

- Lauri


bb-config.gz
Description: Binary data
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: switch_root and /etc/inittab

2021-10-08 Thread Denys Vlasenko
I'm terribly late for this...

On Tue, Jun 15, 2021 at 4:55 PM Porter, Jeremy
 wrote:
> Thank you for the example--that was helpful to see how this works.
>
> I have initramfs in Linux enabled and I've been using that for a long time. I 
> should be able to use switch_root.
>
> I followed the prior suggestion to skip the inittab and use a script. I put a 
> script in /etc/init.d/rcS:
>
> #!/bin/busybox sh
>
> /bin/busybox echo "Running boot script..."
> /bin/busybox echo "Mounting filesystems..."
> /bin/busybox mount -t devpts devpts /dev/pts
> /bin/busybox mount -t tmpfs tmpfs /dev/shm
> /bin/busybox mount -t proc proc /proc
> /bin/busybox mount -t sysfs sysfs /sys
> /bin/busybox mount -t tmpfs tmpfs /tmp
> /bin/busybox echo "Installing links for busybox..."
> /bin/busybox --install -s
> /bin/busybox echo /sbin/mdev > /proc/sys/kernel/hotplug
> /bin/busybox mdev -s
> /bin/busybox echo "mounting rootfs..."
> /bin/busybox mount -t xfs /dev/vda /mnt
> /bin/busybox echo "Swtiching root"
> exec /sbin/switch_root -c /dev/console /mnt /sbin/init
>
> This runs and gets to switch_root.
>
> It does not switch_root though. It doesn't run the new roots inittab which is 
> present.

If switch_root can't/won't chroot to the new root, it prints an error message.
See for yourself:

// Change to new root directory and verify it's a different fs
xchdir(newroot);
xstat("/", );
rootdev = st.st_dev;
xstat(".", );
if (st.st_dev == rootdev) {
// Show usage, it says new root must be a mountpoint
bb_show_usage();
}
if (!dry_run && getpid() != 1) {
// Show usage, it says we must be PID 1
bb_show_usage();
}

// Additional sanity checks: we're about to rm -rf /, so be REALLY SURE
// we mean it. I could make this a CONFIG option, but I would get email
// from all the people who WILL destroy their filesystems.
if (stat("/init", ) != 0 || !S_ISREG(st.st_mode)) {
bb_error_msg_and_die("'%s' is not a regular file", "/init");
}
statfs("/", ); // this never fails
if ((unsigned)stfs.f_type != RAMFS_MAGIC
 && (unsigned)stfs.f_type != TMPFS_MAGIC
) {
bb_simple_error_msg_and_die("root filesystem is not
ramfs/tmpfs");
}

if (!dry_run) {
// Zap everything out of rootdev
delete_contents("/", rootdev);

// Overmount / with newdir and chroot into it
if (mount(".", "/", NULL, MS_MOVE, NULL)) {
// For example, fails when newroot is not a mountpoint
bb_simple_perror_msg_and_die("error moving root");
}
}
xchroot(".");

All error paths have messages. (x-functions (xstat et al) also always
print error messages if they die internally due to errors).

Thus, you should be reaching xchroot().
Then, you should be reaching execv, since it also has error printouts
everywhere else:
if (dry_run) {
// Does NEW_INIT look like it can be executed?
//xstat(argv[0], );
//if (!S_ISREG(st.st_mode))
//  bb_perror_msg_and_die("'%s' is not a regular
file", argv[0]);
if (access(argv[0], X_OK) == 0)
return 0;
} else {
// Exec NEW_INIT
execv(argv[0], argv);
}
bb_perror_msg_and_die("can't execute '%s'", argv[0]);


> I get something like this:
>
> [1.262512] XFS (vda): Ending recovery (logdev: internal)
> Swtiching root
>
> Please press Enter to activate this console.
>
> BusyBox v1.33.1 (2021-06-10 08:53:34 EDT) built-in shell (ash)
>
> / # ls

Looks like you are seeing the new init running default
::askfirst:-/bin/sh
action.

Look around the currently mounted root filesystem and
diagnose why /etc/inittab is not there.


> Is there any good way to debug this switch_root?

You can strace it, I guess...
You can also use

exec /sbin/switch_root -c /dev/console /mnt /bin/sh

which would drop you into a shell, and then see around
what files are in the filesystem, try "exec /sbin/init" etc.



> The new root has /etc/inittab like this:
>
> ::sysinit:-/bin/ash
> ::sysinit:/bin/busybox echo "hello from /etc/inittab"

Do you *see* it in the filesystem when you are in the askfirst shell?
E.g. "cat /etc/inittab" shows the file?
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH] Fix clang barrier for const trick by dummy func

2021-10-08 Thread LoveSy
From: YU Jincheng 

- For clang 9+, `asm volatile ("":::"memory")`
  does not ensure load after a const pointer
  assigned by trick on `ASSIGN_CONST_PTR`
- We found that using a dummy function can do
  this trick so this patch converts `barrier`
  to an invisible dummy function
- This dummy function `barrier` should be
  invisible from the caller to avoid inlining
  by the compiler
- This trick introduces one instruction size
  overhead which should only be 4-8 bytes and
  the runtime overhead is at most one cache
  miss (unconditional branch won't introduce
  branch misprediction penalty)

Signed-off-by: LoveSy 
---
 include/libbb.h|  5 -
 libbb/const_hack.c | 15 +++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 libbb/const_hack.c

diff --git a/include/libbb.h b/include/libbb.h
index 02cc008f0..56b404b03 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2284,7 +2284,6 @@ struct globals;
  * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */
 extern struct globals *const ptr_to_globals;
 
-#define barrier() asm volatile ("":::"memory")
 
 #if defined(__clang_major__) && __clang_major__ >= 9
 /* Clang/llvm drops assignment to "constant" storage. Silently.
@@ -2300,8 +2299,12 @@ static ALWAYS_INLINE void* not_const_pp(const void *p)
);
return pp;
 }
+/* Clang/llvm needs an invisible dummy function for barrier
+ */
+void barrier();
 #else
 static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; }
+#define barrier() asm volatile ("":::"memory")
 #endif
 
 #define ASSIGN_CONST_PTR(p, v) do { \
diff --git a/libbb/const_hack.c b/libbb/const_hack.c
new file mode 100644
index 0..5450b82c6
--- /dev/null
+++ b/libbb/const_hack.c
@@ -0,0 +1,15 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Dummy function as barrier for const trick
+ *
+ * Copyright (C) 2021 by YU Jincheng 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#if defined(__clang_major__) && __clang_major__ >= 9
+void barrier() {
+   // dummy
+   // it should at most cost one instruction (4-8 bytes)
+}
+#endif
\ No newline at end of file
-- 
2.25.1

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] Fix const pointer assignment trick on clang 9+

2021-10-08 Thread 余生与君
On Thu, Oct 7, 2021 at 9:48 PM Denys Vlasenko  wrote:
>
> On Thu, Oct 7, 2021 at 3:25 PM 余生与君  wrote:
> > > where p is a dummy, unused variable
> > No. p here shadows the global variable with the same name local
> > variable so the following context (scope) will use this local variable
> > instead of the global one.
>
> Aha...
> The problem here is that even though later uses of "p" in this block
> where we use ASSIGN_CONST_PTR() macro will use the local "p" pointer,
> when we exit the block, the following uses will refer to the global one.
> Nothing prevents them to still use incorrect value.
> The fix depends only on the hope that there won't be such uses.
> But they already exist:
>
> inetd.c:
> INIT_G();
> real_uid = getuid();
>
> ftpgetput.c:
> INIT_G();
> /* Set default values */
> user = "anonymous";
> password = "busybox";

Yes, I noticed that, and that's why I removed do-while in the INIT_G
in this patch.

> Can you try something more? E.g. (in current git):
>
> #define ASSIGN_CONST_PTR(p, v) do { \
> *(void**)not_const_pp() = (void*)(v); \
> /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
> barrier(); \
> +   sleep(0); \
> } while (0)

Cool! Sleep(0) does the magic!

ADRPX21, #ash_ptr_to_globals_misc_ptr@PAGE
LDR X21, [X21,#ash_ptr_to_globals_misc_ptr@PAGEOFF]
MOV X8, X21
STR X0, [X8]
MOV W0, WZR
BL  sleep
LDR X21, [X21]


And further investigation shows that a dummy function can also do this trick!

hack.c:
void clang_barrier() {
}

libbb.h:
void clang_barrier(); // invisible in this file
#define ASSIGN_CONST_PTR(p, v) do { \
*(void**)not_const_pp() = (void*)(v); \
/* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
-barrier(); \
+   clang_barrier(); \
} while (0)

Result:
ADRPX21, #ash_ptr_to_globals_misc_ptr@PAGE
LDR X21, [X21,#ash_ptr_to_globals_misc_ptr@PAGEOFF]
MOV X8, X21
STR X0, [X8]
BL  clang_barrier
LDR X21, [X21]

I will submit a patch about this.

> or even
>
> -   barrier(); \
> +   pselect(0, NULL, NULL, NULL, {0,0}, NULL); \
>
> Basically, we should convince clang to not load "p" too early,
> by starving it of available registers to store the fetched result.
>
> > > Also, why ({...;})
> > That is to avoid conflict between the global variable and the local
> > variable. When the ({...}) part is evaluating, it uses the global
> > variable p and stores it into the local variable, and then returns the
> > variable to initialize the local variable.
>
> I'm not even sure other compilers would interpret it like that -
> they might think that "p" inside ({}) is the newly defined one.

That's why I only apply it to clang to avoid other compilers having
different behavior.
But in c++14, this is UB. The `p` is the newly defined one. But we can
avoid this to two statements with a tmp variable. But the name can be
conflicted.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


答复: devmem: use mmap64 replace mmap

2021-10-08 Thread xiechengliang
I have built busybox with CONFIG_LFS=y, this problem still exists.

mmap is defined in glibc as below:
void *mmap(void *addr, size_t len, int prot , int flags , int fd, off_t offset);
The type of last parameter offset is off_ t, so using mmap will still cause 
truncation problems.

The mmap64() function is identical to the mmap() function except that it can be 
used to map memory from files that are larger than 2 gigabytes into the process 
memory.


Strace log :
arm32_for_busybox_devmem / # strace devmem 0x28000
execve("/sbin/devmem", ["devmem", "0x28000"], 0xbed2bd24 /* 21 vars */) = 0
...
...
...
mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 3, 0x8000) = 0xb6f36000
...
...
...
exit_group(0)   = ?
+++ exited with 0 +++

-邮件原件-
发件人: Denys Vlasenko [mailto:vda.li...@googlemail.com] 
发送时间: 2021年10月7日 23:35
收件人: xiechengliang 
抄送: busybox@busybox.net
主题: Re: devmem: use mmap64 replace mmap

This should be solvable by building with CONFIG_LFS=y
- this makes off_t 64-bit and makes all operations on files 64-bit aware.

Can you try that?



On Mon, Sep 27, 2021 at 4:06 PM xiechengliang  wrote:
>
> Subject: [PATCH] devmem: The type of the physical address to be 
> accessed by
>
> devmem is off_t, when the 32-bit Linux kernel support lpae, the 
> physical
>
> address can exceed 4G, and accessing or modifying the  address 
> exceeding 4G
>
> will cause truncation.
>
>
>
> functionold new   delta
>
> do_cmd127 127  +0
>
>
>
> Signed-off-by: xiechengliang 
>
> ---
>
> miscutils/devmem.c | 6 +++---
>
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
>
>
> diff --git a/miscutils/devmem.c b/miscutils/devmem.c
>
> index f9f0276bc..594bb440c 100644
>
> --- a/miscutils/devmem.c
>
> +++ b/miscutils/devmem.c
>
> @@ -30,7 +30,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv)
>
>void *map_base, *virt_addr;
>
>uint64_t read_result;
>
>uint64_t writeval = writeval; /* for compiler */
>
> -off_t target;
>
> +   uint64_t target;
>
>unsigned page_size, mapped_size, offset_in_page;
>
>int fd;
>
>unsigned width = 8 * sizeof(int);
>
> @@ -82,12 +82,12 @@ int devmem_main(int argc UNUSED_PARAM, char 
> **argv)
>
>  * Must map two pages to make it possible: */
>
> mapped_size *= 2;
>
>}
>
> -map_base = mmap(NULL,
>
> +   map_base = mmap64(NULL,
>
>   mapped_size,
>
>   argv[3] ? (PROT_READ | PROT_WRITE) : 
> PROT_READ,
>
>   MAP_SHARED,
>
>   fd,
>
> -   target & ~(off_t)(page_size - 1));
>
> +  target & ~(uint64_t)(page_size - 1));
>
>if (map_base == MAP_FAILED)
>
> bb_simple_perror_msg_and_die("mmap");
>
>
>
> --
>
> 2.12.3
>
>
>
> ___
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox