Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47718 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/winegcc/winegcc.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 0ca553318eb..893ad1021ea 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -406,6 +406,10 @@ static strarray *get_link_args( struct options *opts, const char *output_name ) strarray_add( flags, "-image_base" ); strarray_add( flags, opts->image_base ); } + /* On Mac, change -s into -Wl,-x. ld's -s switch + * is deprecated, and it doesn't work on Tiger with + * MH_BUNDLEs anyway + */ if (opts->strip) strarray_add( flags, "-Wl,-x" ); strarray_addall( link_args, flags ); return link_args; @@ -1250,9 +1254,21 @@ static void build(struct options* opts)
if (libgcc) strarray_add(link_args, libgcc);
+ if (opts->target_platform != PLATFORM_APPLE && !is_pe && opts->strip) + strarray_add(link_args, "-s"); + spawn(opts->prefix, link_args, 0); strarray_free (link_args);
+ if (opts->target_platform != PLATFORM_APPLE && is_pe && opts->strip) + { + strarray *strip_args = strarray_fromstring(build_tool_name(opts, "strip", "strip"), " "); + strarray_add(strip_args, "--strip-all"); + strarray_add(strip_args, output_path); + spawn(opts->prefix, strip_args, 1); + strarray_free(strip_args); + } + if (is_pe && opts->wine_builtin) make_wine_builtin( output_path );
/* set the base address with prelink if linker support is not present */ @@ -1626,12 +1642,8 @@ int main(int argc, char **argv) opts.shared = 1; raw_compiler_arg = raw_linker_arg = 0; } - else if (strcmp("-s", argv[i]) == 0 && opts.target_platform == PLATFORM_APPLE) + else if (strcmp("-s", argv[i]) == 0) { - /* On Mac, change -s into -Wl,-x. ld's -s switch - * is deprecated, and it doesn't work on Tiger with - * MH_BUNDLEs anyway - */ opts.strip = 1; raw_linker_arg = 0; } @@ -1666,6 +1678,11 @@ int main(int argc, char **argv) opts.wine_builtin = 1; continue; } + if (!strcmp(Wl->base[j], "--strip-all") || !strcmp(Wl->base[j], "-s")) + { + opts.strip = 1; + continue; + } if (!strcmp(Wl->base[j], "--subsystem") && j < Wl->size - 1) { opts.subsystem = strdup( Wl->base[++j] );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/winegcc/winegcc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 893ad1021ea..d1440a64367 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -209,6 +209,7 @@ struct options int wine_builtin; int unwind_tables; int strip; + int strip_debug; int pic; const char* wine_objdir; const char* winebuild; @@ -1256,6 +1257,8 @@ static void build(struct options* opts)
if (opts->target_platform != PLATFORM_APPLE && !is_pe && opts->strip) strarray_add(link_args, "-s"); + else if (!is_pe && opts->strip_debug) + strarray_add(link_args, "-Wl,--strip-debug");
spawn(opts->prefix, link_args, 0); strarray_free (link_args); @@ -1268,6 +1271,14 @@ static void build(struct options* opts) spawn(opts->prefix, strip_args, 1); strarray_free(strip_args); } + else if (is_pe && opts->strip_debug) + { + strarray *strip_args = strarray_fromstring(build_tool_name(opts, "strip", "strip"), " "); + strarray_add(strip_args, "--strip-debug"); + strarray_add(strip_args, output_path); + spawn(opts->prefix, strip_args, 1); + strarray_free(strip_args); + }
if (is_pe && opts->wine_builtin) make_wine_builtin( output_path );
@@ -1683,6 +1694,11 @@ int main(int argc, char **argv) opts.strip = 1; continue; } + if (!strcmp(Wl->base[j], "--strip-debug") || !strcmp(Wl->base[j], "-S")) + { + opts.strip_debug = 1; + continue; + } if (!strcmp(Wl->base[j], "--subsystem") && j < Wl->size - 1) { opts.subsystem = strdup( Wl->base[++j] );
Linux perf tool cannot parse PE files for debug information, but it also looks for external debug info alongside to the binaries it detects.
We can use this feature to provide DWARF information for PE files by splitting the sections to a separate ELF that perf will understand.
This could also be used to support different debug information formats, or to support split-dwarf option on ELF binaries.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/winegcc/utils.c | 47 ++++++++++++++++++++++++++++++++---- tools/winegcc/utils.h | 3 +++ tools/winegcc/winegcc.c | 33 +++++++++++++++++++++++++ tools/winegcc/winegcc.man.in | 4 +++ 4 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/tools/winegcc/utils.c b/tools/winegcc/utils.c index 3197e46e47d..287a9e8a708 100644 --- a/tools/winegcc/utils.c +++ b/tools/winegcc/utils.c @@ -179,15 +179,36 @@ char* strarray_tostring(const strarray* arr, const char* sep) return str; }
+char* get_dirname(const char* file) +{ + char *dir_name, *p; + + dir_name = xstrdup(file); + if ((p = strrchr(dir_name, '/'))) *p = 0; + else + { + free(dir_name); + dir_name = xstrdup("."); + } + + return dir_name; +} + +char* get_filename(const char* file) +{ + const char *file_name; + + if ((file_name = strrchr(file, '/'))) file_name++; + else file_name = file; + + return xstrdup(file_name); +} + char* get_basename(const char* file) { - const char* name; char *base_name, *p;
- if ((name = strrchr(file, '/'))) name++; - else name = file; - - base_name = strdup(name); + base_name = get_filename(file); if ((p = strrchr(base_name, '.'))) *p = 0;
return base_name; @@ -208,6 +229,22 @@ void create_file(const char* name, int mode, const char* fmt, ...) chmod(name, mode); }
+void create_dir( const char *dir ) +{ + char *p, *path; + + p = path = xstrdup( dir ); + while ((p = strchr( p, '/' ))) + { + *p = 0; + if (mkdir( path, 0755 ) == -1 && errno != EEXIST) error( "mkdir %s", path ); + *p++ = '/'; + while (*p == '/') p++; + } + if (mkdir( path, 0755 ) == -1 && errno != EEXIST) error( "mkdir %s", path ); + free( path ); +} + file_type get_file_type(const char* filename) { /* see tools/winebuild/res32.c: check_header for details */ diff --git a/tools/winegcc/utils.h b/tools/winegcc/utils.h index 3d6b8f3665b..9f3d6f1785d 100644 --- a/tools/winegcc/utils.h +++ b/tools/winegcc/utils.h @@ -80,8 +80,11 @@ typedef enum { file_arh, file_dll, file_so, file_def, file_spec } file_type;
+char* get_dirname(const char* file); +char* get_filename(const char* file); char* get_basename(const char* file); void create_file(const char* name, int mode, const char* fmt, ...); +void create_dir( const char *dir ); file_type get_file_type(const char* filename); file_type get_lib_type(enum target_platform platform, strarray* path, const char *library, const char *suffix, char** file); diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index d1440a64367..98dc2d417a7 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -210,6 +210,7 @@ struct options int unwind_tables; int strip; int strip_debug; + int split_dwarf; int pic; const char* wine_objdir; const char* winebuild; @@ -1263,6 +1264,31 @@ static void build(struct options* opts) spawn(opts->prefix, link_args, 0); strarray_free (link_args);
+ if (build_platform != PLATFORM_APPLE && is_pe && opts->split_dwarf) + { + char const *bfd_format = (opts->target_cpu == CPU_x86_64) ? "-Oelf64-x86-64" : "-Oelf32-i386"; + strarray *objcopy_args = strarray_fromstring(build_tool_name(opts, "objcopy", "objcopy"), " "); + char *debug_path, *file_name; + + file_name = get_filename(output_path); + debug_path = get_dirname(output_path); + debug_path = realloc(debug_path, strlen(debug_path) + strlen("/.debug/") + strlen(file_name) + 1); + + strcat(debug_path, "/.debug/"); + create_dir(debug_path); + + strcat(debug_path, file_name); + free(file_name); + + strarray_add(objcopy_args, bfd_format); + strarray_add(objcopy_args, "--only-keep-debug"); + strarray_add(objcopy_args, output_path); + strarray_add(objcopy_args, debug_path); + spawn(opts->prefix, objcopy_args, 1); + strarray_free(objcopy_args); + free(debug_path); + } + if (opts->target_platform != PLATFORM_APPLE && is_pe && opts->strip) { strarray *strip_args = strarray_fromstring(build_tool_name(opts, "strip", "strip"), " "); @@ -1557,6 +1583,13 @@ int main(int argc, char **argv) case 'i': if (!strcmp( "-isysroot", argv[i] )) opts.isysroot = argv[i + 1]; break; + case 'g': + if (strcmp("-gsplit-dwarf", argv[i]) == 0) + { + opts.split_dwarf = 1; + raw_compiler_arg = 0; + } + break; case 'l': strarray_add(opts.files, strmake("-l%s", option_arg)); raw_compiler_arg = 0; diff --git a/tools/winegcc/winegcc.man.in b/tools/winegcc/winegcc.man.in index 5550767299b..7b6f420a2ed 100644 --- a/tools/winegcc/winegcc.man.in +++ b/tools/winegcc/winegcc.man.in @@ -41,6 +41,10 @@ precedence over the \fBWINEBUILD\fR environment variable. Override the underlying type for wchar_t to be the default for the target, instead of using short unsigned int, which is the default for Win32. +.IP \fB-gsplit-dwarf\fR +Split debug sections from PE files to a separate ELF binary. This can +be used to help tools like \fBperf\fR, that only support ELF parsing, +load the debug sections. .IP \fB-mconsole\fR This option passes '--subsystem console' to winebuild, to build console applications. It is the default.
This should help linux perf tool match the binary files on disk with the code regions in memory.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/makedep.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/tools/makedep.c b/tools/makedep.c index 67dfea43bb3..6d74507661e 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -3247,6 +3247,7 @@ static void output_module( struct makefile *make ) output_filenames_obj_dir( make, make->res_files ); output_filenames( all_libs ); output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" ); + output_filename( make->is_cross ? "-Wl,--file-alignment,4096" : "" ); output( "\n" );
if (spec_file && make->importlib)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/makedep.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/tools/makedep.c b/tools/makedep.c index 6d74507661e..c5d1dd746cc 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -2333,6 +2333,7 @@ static void output_winegcc_command( struct makefile *make ) output_filename( "-b" ); output_filename( crosstarget ); output_filename( "--lib-suffix=.cross.a" ); + output_filename( "-gsplit-dwarf" ); } else {