Re: Inflation of vmlinux by linker on x86_64

From: Joris van Rantwijk
Date: Fri Sep 26 2008 - 17:55:48 EST


On Fri, Sep 26, 2008 at 01:07:11PM -0700, H. Peter Anvin wrote:
> In this case, I think the easiest thing to do is to provide an optimized
> memmove and not making it a static function. I have a reasonably
> optimized memmove in 32-bit assembly at:
> http://git.kernel.org/?p=boot/syslinux/syslinux.git;a=blob;f=com32/lib/memmove.S;hb=HEAD

Ok. Right now, I'd like to focus on the semantics, preferably without
bringing in new assembler code. I renamed memcpy to memmove and
dropped "static". We can always replace it with optimized code
as a separate patch.

There is still the question whether linking vmlinux with -n (turn off
file offset alignment) works on all architectures. I suspect not.

Joris.

diff -urN linux-2.6.27-rc7/Makefile linux-2.6.27-rc7j/Makefile
--- linux-2.6.27-rc7/Makefile 2008-09-26 23:01:41.000000000 +0200
+++ linux-2.6.27-rc7j/Makefile 2008-09-26 12:21:34.000000000 +0200
@@ -577,7 +577,7 @@
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
$(call ld-option, -Wl$(comma)--build-id,))
LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
-LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)
+LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID) -n

# Default kernel image to build when no specific target is given.
# KBUILD_IMAGE may be overruled on the command line or
diff -urN linux-2.6.27-rc7/arch/x86/boot/compressed/misc.c linux-2.6.27-rc7j/arch/x86/boot/compressed/misc.c
--- linux-2.6.27-rc7/arch/x86/boot/compressed/misc.c 2008-09-26 23:01:41.000000000 +0200
+++ linux-2.6.27-rc7j/arch/x86/boot/compressed/misc.c 2008-09-26 23:02:14.000000000 +0200
@@ -27,6 +27,7 @@
#include <linux/linkage.h>
#include <linux/screen_info.h>
#include <linux/elf.h>
+#include <linux/types.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/boot.h>
@@ -122,6 +123,7 @@

#undef memset
#undef memcpy
+#define memcpy memmove
#define memzero(s, n) memset((s), 0, (n))

typedef unsigned char uch;
@@ -195,7 +197,7 @@
static long bytes_out;

static void *memset(void *s, int c, unsigned n);
-static void *memcpy(void *dest, const void *src, unsigned n);
+void *memmove(void *dest, const void *src, size_t n);

static void __putstr(int, const char *);
#define putstr(__x) __putstr(0, __x)
@@ -281,13 +283,18 @@
return s;
}

-static void *memcpy(void *dest, const void *src, unsigned n)
+/* memmove can not be static due to a declaration in asm-x86/string_32.h */
+void *memmove(void *dest, const void *src, size_t n)
{
- int i;
+ size_t i;
const char *s = src;
char *d = dest;

- for (i = 0; i < n; i++) d[i] = s[i];
+ if (dest <= src) {
+ for (i = 0; i < n; i++) d[i] = s[i];
+ } else {
+ for (i = n; i > 0; i--) d[i-1] = s[i-1];
+ }
return dest;
}

@@ -343,8 +350,8 @@
Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs, *phdr;
#endif
- void *dest;
- int i;
+ void *dest, *src;
+ int i, direction;

memcpy(&ehdr, output, sizeof(ehdr));
if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
@@ -364,7 +371,17 @@

memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);

- for (i = 0; i < ehdr.e_phnum; i++) {
+ /* Go two times through the list of program headers;
+ * first forward, then backward.
+ */
+ for (i = 0, direction = 1; i >= 0; i += direction) {
+
+ if (i >= ehdr.e_phnum) {
+ /* reached the end; turn back */
+ direction = -1;
+ continue;
+ }
+
phdr = &phdrs[i];

switch (phdr->p_type) {
@@ -375,9 +392,14 @@
#else
dest = (void *)(phdr->p_paddr);
#endif
- memcpy(dest,
- output + phdr->p_offset,
- phdr->p_filesz);
+ src = output + phdr->p_offset;
+
+ /* order the copying to avoid overwriting */
+ if ((direction == 1 && dest <= src) ||
+ (direction == -1 && dest > src)) {
+ memmove(dest, src, phdr->p_filesz);
+ }
+
break;
default: /* Ignore other PT_* */ break;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/