summaryrefslogtreecommitdiffstats
path: root/libdwfl
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl')
-rw-r--r--libdwfl/ChangeLog39
-rw-r--r--libdwfl/argp-std.c2
-rw-r--r--libdwfl/dwfl_build_id_find_elf.c9
-rw-r--r--libdwfl/dwfl_error.c4
-rw-r--r--libdwfl/dwfl_module_getdwarf.c2
-rw-r--r--libdwfl/dwfl_report_elf.c2
-rw-r--r--libdwfl/dwfl_segment_report_module.c2
-rw-r--r--libdwfl/find-debuginfo.c117
-rw-r--r--libdwfl/libdwflP.h4
-rw-r--r--libdwfl/link_map.c4
-rw-r--r--libdwfl/linux-kernel-modules.c24
-rw-r--r--libdwfl/linux-pid-attach.c6
-rw-r--r--libdwfl/linux-proc-maps.c14
-rw-r--r--libdwfl/offline.c2
14 files changed, 146 insertions, 85 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index acb4236a..d03268b6 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,40 @@
+2017-05-04 Ulf Hermann <[email protected]>
+
+ * find-debuginfo.c: On windows, check various extra parameters of
+ struct stat to determine if two files are the same.
+
+2017-05-04 Ulf Hermann <[email protected]>
+
+ * dwfl_build_id_find_elf.c: Don't assume unix file system conventions.
+ * find-debuginfo.c: Likewise.
+ * linux-kernel-modules.c: Likewise.
+ * linux-proc-maps.c: Likewise.
+ * libdwflP.h: Add a windows-compatible default debuginfo path.
+
+2017-05-04 Ulf Hermann <[email protected]>
+
+ * argp-std.c: Open files in O_BINARY.
+ * dwfl_build_id_find_elf.c: Likewise.
+ * dwfl_build_id_find_elf.c: Likewise.
+ * dwfl_module_getdwarf.c: Likewise.
+ * dwfl_report_elf.c: Likewise.
+ * dwfl_segment_report_module.c: Likewise.
+ * find-debuginfo.c: Likewise.
+ * link_map.c: Likewise.
+ * linux-kernel-modules.c: Likewise.
+ * linux-pid-attach.c: Likewise.
+ * linux-proc-maps.c: Likewise.
+ * offline.c: Likewise.
+
+2017-04-27 Ulf Hermann <[email protected]>
+
+ * linux-kernel-modules.c: Don't include system.h.
+
+2017-02-22 Ulf Hermann <[email protected]>
+
+ * dwfl_error.c: If we don't have a strerror_r returning a char*,
+ output a less useful message in case of a system error.
+
2018-06-04 Mark Wielaard <[email protected]>
* libdwflP.h (__libdwfl_addrsym): Remove function declaration.
@@ -169,7 +206,7 @@
* linux-pid-attach.c: Include sys/ptrace.h and sys/syscall.h only on
linux.
-2017-04-20 Ulf Hermann <[email protected]>
+2017-04-20 Ulf Hermann <[email protected]>
* linux-kernel-modules.c: Include sys/types.h before fts.h
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 8ee91587..fbdbb231 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -280,7 +280,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (opt->core)
{
- int fd = open (opt->core, O_RDONLY);
+ int fd = open (opt->core, O_RDONLY | O_BINARY);
if (fd < 0)
{
int code = errno;
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
index cc6c3f62..1cf2751c 100644
--- a/libdwfl/dwfl_build_id_find_elf.c
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -79,13 +79,14 @@ __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name,
int fd = -1;
char *dir;
char *paths = path;
- while (fd < 0 && (dir = strsep (&paths, ":")) != NULL)
+ char pathsep[] = { PATHSEP, '\0' };
+ while (fd < 0 && (dir = strsep (&paths, pathsep)) != NULL)
{
if (dir[0] == '+' || dir[0] == '-')
++dir;
/* Only absolute directory names are useful to us. */
- if (dir[0] != '/')
+ if (IS_ABSOLUTE_PATH(dir))
continue;
size_t dirlen = strlen (dir);
@@ -94,7 +95,7 @@ __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name,
break;
memcpy (mempcpy (name, dir, dirlen), id_name, sizeof id_name);
- fd = TEMP_FAILURE_RETRY (open (name, O_RDONLY));
+ fd = TEMP_FAILURE_RETRY (open (name, O_RDONLY | O_BINARY));
if (fd >= 0)
{
if (*file_name != NULL)
@@ -154,7 +155,7 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
recorded executable file when MOD was identified as main executable
(which then triggers opening and reporting of the executable). */
const char *executable = mod->dwfl->user_core->executable_for_core;
- int fd = open (executable, O_RDONLY);
+ int fd = open (executable, O_RDONLY | O_BINARY);
if (fd >= 0)
{
*file_name = strdup (executable);
diff --git a/libdwfl/dwfl_error.c b/libdwfl/dwfl_error.c
index 7bcf61cc..aba3cca8 100644
--- a/libdwfl/dwfl_error.c
+++ b/libdwfl/dwfl_error.c
@@ -154,7 +154,11 @@ dwfl_errmsg (int error)
switch (error &~ 0xffff)
{
case OTHER_ERROR (ERRNO):
+#ifdef STRERROR_R_CHAR_P
return strerror_r (error & 0xffff, "bad", 0);
+#else
+ return "Unknown error. See errno";
+#endif
case OTHER_ERROR (LIBELF):
return elf_errmsg (error & 0xffff);
case OTHER_ERROR (LIBDW):
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index af6838a6..095a853f 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -51,7 +51,7 @@ open_elf_file (Elf **elf, int *fd, char **name)
/* If there was a pre-primed file name left that the callback left
behind, try to open that file name. */
if (*fd < 0 && *name != NULL)
- *fd = TEMP_FAILURE_RETRY (open (*name, O_RDONLY));
+ *fd = TEMP_FAILURE_RETRY (open (*name, O_RDONLY | O_BINARY));
if (*fd < 0)
return CBFAIL;
diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c
index 3fc9384a..57f58538 100644
--- a/libdwfl/dwfl_report_elf.c
+++ b/libdwfl/dwfl_report_elf.c
@@ -295,7 +295,7 @@ dwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
if (fd < 0)
{
closefd = true;
- fd = open (file_name, O_RDONLY);
+ fd = open (file_name, O_RDONLY | O_BINARY);
if (fd < 0)
{
__libdwfl_seterrno (DWFL_E_ERRNO);
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 207a2573..cd8f6135 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -688,7 +688,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
name = file_note_name;
name_is_final = true;
bool invalid = false;
- fd = open (name, O_RDONLY);
+ fd = open (name, O_RDONLY | O_BINARY);
if (fd >= 0)
{
Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
diff --git a/libdwfl/find-debuginfo.c b/libdwfl/find-debuginfo.c
index 9267788d..96f98cac 100644
--- a/libdwfl/find-debuginfo.c
+++ b/libdwfl/find-debuginfo.c
@@ -52,20 +52,30 @@ try_open (const struct stat *main_stat,
if (unlikely (fname == NULL))
return -1;
}
- else if ((subdir == NULL ? asprintf (&fname, "%s/%s", dir, debuglink)
- : dir == NULL ? asprintf (&fname, "%s/%s", subdir, debuglink)
- : asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink)) < 0)
+ else if ((subdir == NULL ? asprintf (&fname, "%s%c%s", dir, DIRSEP, debuglink)
+ : dir == NULL ? asprintf (&fname, "%s%c%s", subdir, DIRSEP, debuglink)
+ : asprintf (&fname, "%s%c%s%c%s", dir, DIRSEP, subdir, DIRSEP,
+ debuglink)) < 0)
return -1;
struct stat st;
- int fd = TEMP_FAILURE_RETRY (open (fname, O_RDONLY));
+ int fd = TEMP_FAILURE_RETRY (open (fname, O_RDONLY | O_BINARY));
if (fd < 0)
free (fname);
else if (fstat (fd, &st) == 0
+#if defined _WIN32 || defined __WIN32__
+ /* On windows, st_ino and st_dev are not unique, so we apply a heuristic */
+ && st.st_size == main_stat->st_size
+ && st.st_mode == main_stat->st_mode
+ && st.st_mtime == main_stat->st_mtime
+ && st.st_ctime == main_stat->st_ctime
+#endif
&& st.st_ino == main_stat->st_ino
&& st.st_dev == main_stat->st_dev)
{
/* This is the main file by another name. Don't look at it again. */
+ /* This doesn't happen on windows as windows doesn't have proper links. However, on windows
+ st_ino and st_dev is always 0. */
free (fname);
close (fd);
errno = ENOENT;
@@ -231,7 +241,8 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
return -1;
}
char *p;
- while ((p = strsep (&path, ":")) != NULL)
+ const char pathsep[] = { PATHSEP, '\0' };
+ while ((p = strsep (&path, pathsep)) != NULL)
{
/* A leading - or + says whether to check file CRCs for this element. */
bool check = defcheck;
@@ -244,53 +255,57 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
bool try_file_basename;
const char *dir, *subdir, *file;
- switch (p[0])
- {
- case '\0':
- /* An empty entry says to try the main file's directory. */
- dir = file_dirname;
- subdir = NULL;
- file = debuglink_file;
- try_file_basename = false;
- break;
- case '/':
- /* An absolute path says to look there for a subdirectory
- named by the main file's absolute directory. This cannot
- be applied to a relative file name. For alt debug files
- it means to look for the basename file in that dir or the
- .dwz subdir (see below). */
- if (mod->dw == NULL
- && (file_dirname == NULL || file_dirname[0] != '/'))
- continue;
- dir = p;
- if (mod->dw == NULL)
- {
- subdir = file_dirname;
- /* We want to explore all sub-subdirs. Chop off one slash
- at a time. */
- explore_dir:
- subdir = strchr (subdir, '/');
- if (subdir != NULL)
- subdir = subdir + 1;
- if (subdir && *subdir == 0)
- continue;
- file = debuglink_file;
- }
- else
- {
+ if (IS_ABSOLUTE_PATH(p))
+ {
+ /* An absolute path says to look there for a subdirectory
+ named by the main file's absolute directory. This cannot
+ be applied to a relative file name. For alt debug files
+ it means to look for the basename file in that dir or the
+ .dwz subdir (see below). */
+ if (mod->dw == NULL
+ && (file_dirname == NULL || !IS_ABSOLUTE_PATH(file_dirname)))
+ continue;
+ dir = p;
+ if (mod->dw == NULL) {
+ subdir = file_dirname;
+ /* We want to explore all sub-subdirs. Chop off one slash
+ at a time. */
+ explore_dir:
+ while (subdir && *subdir && !ISDIRSEP(*subdir))
+ ++subdir;
+ if (subdir != NULL && *subdir != 0)
+ subdir = subdir + 1;
+ if (subdir && *subdir == 0)
+ continue;
+ file = debuglink_file;
+ }
+ else
+ {
+ subdir = NULL;
+ file = basename (debuglink_file);
+ }
+ try_file_basename = debuglink_null;
+ }
+ else
+ {
+ switch (p[0])
+ {
+ case '\0':
+ /* An empty entry says to try the main file's directory. */
+ dir = file_dirname;
subdir = NULL;
- file = basename (debuglink_file);
+ file = debuglink_file;
+ try_file_basename = false;
+ break;
+ default:
+ /* A relative path says to try a subdirectory of that name
+ in the main file's directory. */
+ dir = file_dirname;
+ subdir = p;
+ file = debuglink_file;
+ try_file_basename = debuglink_null;
+ break;
}
- try_file_basename = debuglink_null;
- break;
- default:
- /* A relative path says to try a subdirectory of that name
- in the main file's directory. */
- dir = file_dirname;
- subdir = p;
- file = debuglink_file;
- try_file_basename = debuglink_null;
- break;
}
char *fname = NULL;
@@ -304,7 +319,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
case ENOTDIR:
/* If we are looking for the alt file also try the .dwz subdir.
But only if this is the empty or absolute path. */
- if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/'))
+ if (mod->dw != NULL && (p[0] == '\0' || IS_ABSOLUTE_PATH(p)))
{
fd = try_open (&main_stat, dir, ".dwz",
basename (file), &fname);
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 31e6e190..dcdb332c 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -771,7 +771,11 @@ INTDECL (dwfl_frame_pc)
/* The default used by dwfl_standard_find_debuginfo. */
+#if (defined _WIN32 || defined __WIN32__)
+#define DEFAULT_DEBUGINFO_PATH ";.debug"
+#else
#define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
+#endif
#endif /* libdwflP.h */
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 29307c74..937cc1a0 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -389,7 +389,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
{
/* This code is mostly inlined dwfl_report_elf. */
// XXX hook for sysroot
- int fd = open (name, O_RDONLY);
+ int fd = open (name, O_RDONLY | O_BINARY);
if (fd >= 0)
{
Elf *elf;
@@ -808,7 +808,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
core file. */
- int fd = open (dwfl->user_core->executable_for_core, O_RDONLY);
+ int fd = open (dwfl->user_core->executable_for_core, O_RDONLY | O_BINARY);
Elf *elf;
Dwfl_Error error = DWFL_E_ERRNO;
if (fd != -1)
diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c
index 9d0fef2c..4b454d37 100644
--- a/libdwfl/linux-kernel-modules.c
+++ b/libdwfl/linux-kernel-modules.c
@@ -37,7 +37,6 @@
#endif
#include <config.h>
-#include <system.h>
#include "libdwflP.h"
#include <inttypes.h>
@@ -49,6 +48,7 @@
#include <sys/utsname.h>
#include <fcntl.h>
#include <unistd.h>
+#include <system.h>
/* If fts.h is included before config.h, its indirect inclusions may not
give us the right LFS aliases of these functions, so map them manually. */
@@ -97,8 +97,8 @@ try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
tried because we give its own basename as DEBUGLINK_FILE. */
int fd = ((((dwfl->callbacks->debuginfo_path
? *dwfl->callbacks->debuginfo_path : NULL)
- ?: DEFAULT_DEBUGINFO_PATH)[0] == ':') ? -1
- : TEMP_FAILURE_RETRY (open (*fname, O_RDONLY)));
+ ?: DEFAULT_DEBUGINFO_PATH)[0] == PATHSEP) ? -1
+ : TEMP_FAILURE_RETRY (open (*fname, O_RDONLY | O_BINARY)));
if (fd < 0)
{
@@ -133,7 +133,7 @@ try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
char *zname;
if (asprintf (&zname, "%s%s", *fname, vmlinux_suffixes[i]) > 0)
{
- fd = TEMP_FAILURE_RETRY (open (zname, O_RDONLY));
+ fd = TEMP_FAILURE_RETRY (open (zname, O_RDONLY | O_BINARY));
if (fd < 0)
free (zname);
else
@@ -492,7 +492,7 @@ intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
{
struct read_address_state state = { NULL, NULL, 0, 0, NULL, NULL };
- state.f = fopen (KSYMSFILE, "r");
+ state.f = fopen (KSYMSFILE, "rb");
if (state.f == NULL)
return errno;
@@ -535,7 +535,7 @@ static int
check_notes (Dwfl_Module *mod, const char *notesfile,
Dwarf_Addr vaddr, const char *secname)
{
- int fd = open (notesfile, O_RDONLY);
+ int fd = open (notesfile, O_RDONLY | O_BINARY);
if (fd < 0)
return 1;
@@ -793,7 +793,7 @@ dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
&& (!memcmp (f->fts_name, module_name, namelen)
|| !memcmp (f->fts_name, alternate_name, namelen)))
{
- int fd = open (f->fts_accpath, O_RDONLY);
+ int fd = open (f->fts_accpath, O_RDONLY | O_BINARY);
*file_name = strdup (f->fts_path);
fts_close (fts);
free (modulesdir[0]);
@@ -846,7 +846,7 @@ dwfl_linux_kernel_module_section_address
if (asprintf (&sysfile, SECADDRDIRFMT "%s", modname, secname) < 0)
return DWARF_CB_ABORT;
- FILE *f = fopen (sysfile, "r");
+ FILE *f = fopen (sysfile, "rb");
free (sysfile);
if (f == NULL)
@@ -880,7 +880,7 @@ dwfl_linux_kernel_module_section_address
if (asprintf (&sysfile, SECADDRDIRFMT "_%s",
modname, &secname[1]) < 0)
return ENOMEM;
- f = fopen (sysfile, "r");
+ f = fopen (sysfile, "rb");
free (sysfile);
if (f != NULL)
goto ok;
@@ -900,11 +900,11 @@ dwfl_linux_kernel_module_section_address
do
{
*--end = '\0';
- f = fopen (sysfile, "r");
+ f = fopen (sysfile, "rb");
if (is_init && f == NULL && errno == ENOENT)
{
sysfile[len - namelen] = '_';
- f = fopen (sysfile, "r");
+ f = fopen (sysfile, "rb");
sysfile[len - namelen] = '.';
}
}
@@ -938,7 +938,7 @@ INTDEF (dwfl_linux_kernel_module_section_address)
int
dwfl_linux_kernel_report_modules (Dwfl *dwfl)
{
- FILE *f = fopen (MODULELIST, "r");
+ FILE *f = fopen (MODULELIST, "rb");
if (f == NULL)
return errno;
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 1133db6c..7e0ff466 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -53,7 +53,7 @@ linux_proc_pid_is_stopped (pid_t pid)
bool retval, have_state;
snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
- procfile = fopen (buffer, "r");
+ procfile = fopen (buffer, "rb");
if (procfile == NULL)
return false;
@@ -383,7 +383,7 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
/* Make sure to report the actual PID (thread group leader) to
dwfl_attach_state. */
snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
- procfile = fopen (buffer, "r");
+ procfile = fopen (buffer, "rb");
if (procfile == NULL)
{
err = errno;
@@ -433,7 +433,7 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
Elf *elf;
i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
- int elf_fd = open (name, O_RDONLY);
+ int elf_fd = open (name, O_RDONLY | O_BINARY);
if (elf_fd >= 0)
{
elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index c4438c0f..8eb9a5cb 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -63,7 +63,7 @@ get_pid_class (pid_t pid)
if (asprintf (&fname, PROCEXEFMT, pid) < 0)
return ELFCLASSNONE;
- int fd = open (fname, O_RDONLY);
+ int fd = open (fname, O_RDONLY | O_BINARY);
free (fname);
if (fd < 0)
return ELFCLASSNONE;
@@ -99,7 +99,7 @@ grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
if (asprintf (&fname, PROCAUXVFMT, pid) < 0)
return ENOMEM;
- int fd = open (fname, O_RDONLY);
+ int fd = open (fname, O_RDONLY | O_BINARY);
free (fname);
if (fd < 0)
return errno == ENOENT ? 0 : errno;
@@ -245,7 +245,7 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
}
char *file = line + nread + strspn (line + nread, " \t");
- if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0))
+ if (!IS_ABSOLUTE_PATH(file) || (ino == 0 && dmajor == 0 && dminor == 0))
/* This line doesn't indicate a file mapping. */
continue;
@@ -306,7 +306,7 @@ dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
if (asprintf (&fname, PROCMAPSFMT, pid) < 0)
return ENOMEM;
- FILE *f = fopen (fname, "r");
+ FILE *f = fopen (fname, "rb");
free (fname);
if (f == NULL)
return errno;
@@ -362,7 +362,7 @@ dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
char **file_name, Elf **elfp)
{
int pid = -1;
- if (module_name[0] == '/')
+ if (IS_ABSOLUTE_PATH (module_name))
{
/* When this callback is used together with dwfl_linux_proc_report
then we might see mappings of special character devices. Make
@@ -380,7 +380,7 @@ dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
if (pid == -1)
{
- int fd = open (module_name, O_RDONLY);
+ int fd = open (module_name, O_RDONLY | O_BINARY);
if (fd >= 0)
{
*file_name = strdup (module_name);
@@ -417,7 +417,7 @@ dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
if (asprintf (&fname, PROCMEMFMT, pid) < 0)
goto detach;
- int fd = open (fname, O_RDONLY);
+ int fd = open (fname, O_RDONLY | O_BINARY);
free (fname);
if (fd < 0)
goto detach;
diff --git a/libdwfl/offline.c b/libdwfl/offline.c
index d8697cf2..be34a63f 100644
--- a/libdwfl/offline.c
+++ b/libdwfl/offline.c
@@ -305,7 +305,7 @@ dwfl_report_offline (Dwfl *dwfl, const char *name,
if (fd < 0)
{
closefd = true;
- fd = open (file_name, O_RDONLY);
+ fd = open (file_name, O_RDONLY | O_BINARY);
if (fd < 0)
{
__libdwfl_seterrno (DWFL_E_ERRNO);