Commit 4a116813 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] kbuild: fix modpost when used with O=

From: Sam Ravnborg <sam@ravnborg.org>

modpost or to be more specific sumversion.c was not behaving correct when
used with O= and MODULE_VERSION was used.  Previously it failed to use
local .h when calculation the md-sum in case of a O= build.

The following patch introduces the following:

- A generic get_next_line()

- Check that the topmost part of the directory matches

- Using strrch when checking for file with suffix .o

- Use NOFAIL for allocations in sumversion

- Avoid memory leak in new_module

The generic get_next_line will pay off when Andreas implmentation of
storing symbol addresses in a seperate file is introduced.
parent 2d86075a
......@@ -11,6 +11,7 @@
* Usage: modpost vmlinux module1.o module2.o ...
*/
#include <ctype.h>
#include "modpost.h"
/* Are we using CONFIG_MODVERSIONS? */
......@@ -44,8 +45,6 @@ warn(const char *fmt, ...)
va_end(arglist);
}
#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
void *do_nofail(void *ptr, const char *file, int line, const char *expr)
{
if (!ptr) {
......@@ -63,21 +62,19 @@ struct module *
new_module(char *modname)
{
struct module *mod;
char *p;
size_t len;
char *p, *s;
mod = NOFAIL(malloc(sizeof(*mod)));
memset(mod, 0, sizeof(*mod));
p = NOFAIL(strdup(modname));
len = strlen(p);
/* strip trailing .o */
if (len > 2 && p[len-2] == '.' && p[len-1] == 'o')
p[len -2] = '\0';
if ((s = strrchr(p, '.')) != NULL)
if (strcmp(s, ".o") == 0)
*s = '\0';
/* add to list */
mod->name = NOFAIL(strdup(p));
mod->name = p;
mod->next = modules;
modules = mod;
......@@ -209,6 +206,42 @@ grab_file(const char *filename, unsigned long *size)
return map;
}
/*
Return a copy of the next line in a mmap'ed file.
spaces in the beginning of the line is trimmed away.
Return a pointer to a static buffer.
*/
char*
get_next_line(unsigned long *pos, void *file, unsigned long size)
{
static char line[4096];
int skip = 1;
size_t len = 0;
char *p = (char *)file + *pos;
char *s = line;
for (; *pos < size ; (*pos)++)
{
if (skip && isspace(*p)) {
p++;
continue;
}
skip = 0;
if (*p != '\n' && (*pos < size)) {
len++;
*s++ = *p++;
if (len > 4095)
break; /* Too long, stop */
} else {
/* End of string */
*s = '\0';
return line;
}
}
/* End of buffer */
return NULL;
}
void
release_file(void *file, unsigned long size)
{
......
......@@ -53,6 +53,9 @@ static inline void __endian(const void *src, void *dest, unsigned int size)
#endif
#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
void *do_nofail(void *ptr, const char *file, int line, const char *expr);
struct buffer {
char *p;
int pos;
......@@ -95,4 +98,5 @@ void maybe_frob_version(const char *modfilename,
unsigned long modinfo_offset);
void *grab_file(const char *filename, unsigned long *size);
char* get_next_line(unsigned long *pos, void *file, unsigned long size);
void release_file(void *file, unsigned long size);
......@@ -323,12 +323,12 @@ static int parse_file(const char *fname, struct md4_ctx *md)
* figure out source file. */
static int parse_source_files(const char *objfile, struct md4_ctx *md)
{
char *cmd, *file, *p, *end;
char *cmd, *file, *line, *dir;
const char *base;
unsigned long flen;
int dirlen, ret = 0;
unsigned long flen, pos = 0;
int dirlen, ret = 0, check_files = 0;
cmd = malloc(strlen(objfile) + sizeof("..cmd"));
cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd")));
base = strrchr(objfile, '/');
if (base) {
......@@ -339,6 +339,9 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
dirlen = 0;
sprintf(cmd, ".%s.cmd", objfile);
}
dir = NOFAIL(malloc(dirlen + 1));
strncpy(dir, objfile, dirlen);
dir[dirlen] = '\0';
file = grab_file(cmd, &flen);
if (!file) {
......@@ -357,48 +360,38 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
Sum all files in the same dir or subdirs.
*/
/* Strictly illegal: file is not nul terminated. */
p = strstr(file, "\ndeps_");
if (!p) {
fprintf(stderr, "Warning: could not find deps_ line in %s\n",
cmd);
goto out_file;
}
p = strstr(p, ":=");
if (!p) {
fprintf(stderr, "Warning: could not find := line in %s\n",
cmd);
goto out_file;
while ((line = get_next_line(&pos, file, flen)) != NULL) {
char* p = line;
if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
check_files = 1;
continue;
}
p += strlen(":=");
p += strspn(p, " \\\n");
if (!check_files)
continue;
end = strstr(p, "\n\n");
if (!end) {
fprintf(stderr, "Warning: could not find end line in %s\n",
cmd);
goto out_file;
/* Continue until line does not end with '\' */
if ( *(p + strlen(p)-1) != '\\')
break;
/* Terminate line at first space, to get rid of final ' \' */
while (*p) {
if isspace(*p) {
*p = '\0';
break;
}
p++;
}
while (p < end) {
unsigned int len;
len = strcspn(p, " \\\n");
if (memcmp(objfile, p, dirlen) == 0) {
char source[len + 1];
memcpy(source, p, len);
source[len] = '\0';
printf("parsing %s\n", source);
if (!parse_file(source, md)) {
/* Check if this file is in same dir as objfile */
if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
if (!parse_file(line, md)) {
fprintf(stderr,
"Warning: could not open %s: %s\n",
source, strerror(errno));
line, strerror(errno));
goto out_file;
}
}
p += len;
p += strspn(p, " \\\n");
}
/* Everyone parsed OK */
......@@ -406,6 +399,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
out_file:
release_file(file, flen);
out:
free(dir);
free(cmd);
return ret;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment