diff --git a/libc-test/build.rs b/libc-test/build.rs
index 552642fed9f5f06443d29bf120d06ba017c69bd5..35a042001bc75ddd837a612e2f5be15320fa235b 100755
--- a/libc-test/build.rs
+++ b/libc-test/build.rs
@@ -287,9 +287,11 @@ fn test_openbsd(target: &str) {
     cfg.flag("-Wno-deprecated-declarations");
 
     headers! { cfg:
+        "elf.h",
         "errno.h",
         "fcntl.h",
         "limits.h",
+        "link.h",
         "locale.h",
         "stddef.h",
         "stdint.h",
@@ -387,7 +389,9 @@ fn test_openbsd(target: &str) {
     cfg.type_name(move |ty, is_struct, is_union| {
         match ty {
             // Just pass all these through, no need for a "struct" prefix
-            "FILE" | "DIR" | "Dl_info" => ty.to_string(),
+            "FILE" | "DIR" | "Dl_info" | "Elf32_Phdr" | "Elf64_Phdr" => {
+                ty.to_string()
+            }
 
             // OSX calls this something else
             "sighandler_t" => "sig_t".to_string(),
@@ -418,6 +422,15 @@ fn test_openbsd(target: &str) {
         struct_ == "siginfo_t" && field == "si_addr"
     });
 
+    cfg.skip_field(|struct_, field| {
+        match (struct_, field) {
+            // conflicting with `p_type` macro from <resolve.h>.
+            ("Elf32_Phdr", "p_type") => true,
+            ("Elf64_Phdr", "p_type") => true,
+            _ => false,
+        }
+    });
+
     cfg.generate("../src/lib.rs", "main.rs");
 }
 
@@ -870,9 +883,11 @@ fn test_netbsd(target: &str) {
 
     headers! {
         cfg:
+        "elf.h",
         "errno.h",
         "fcntl.h",
         "limits.h",
+        "link.h",
         "locale.h",
         "stddef.h",
         "stdint.h",
@@ -1061,6 +1076,15 @@ fn test_netbsd(target: &str) {
         (struct_ == "aiocb" && field == "aio_buf")
     });
 
+    cfg.skip_field(|struct_, field| {
+        match (struct_, field) {
+            // conflicting with `p_type` macro from <resolve.h>.
+            ("Elf32_Phdr", "p_type") => true,
+            ("Elf64_Phdr", "p_type") => true,
+            _ => false,
+        }
+    });
+
     cfg.generate("../src/lib.rs", "main.rs");
 }
 
@@ -1633,6 +1657,7 @@ fn test_freebsd(target: &str) {
                 "ctype.h",
                 "dirent.h",
                 "dlfcn.h",
+                "elf.h",
                 "errno.h",
                 "fcntl.h",
                 "glob.h",
@@ -1641,6 +1666,7 @@ fn test_freebsd(target: &str) {
                 "langinfo.h",
                 "libutil.h",
                 "limits.h",
+                "link.h",
                 "locale.h",
                 "machine/reg.h",
                 "mqueue.h",
@@ -1709,7 +1735,8 @@ fn test_freebsd(target: &str) {
     cfg.type_name(move |ty, is_struct, is_union| {
         match ty {
             // Just pass all these through, no need for a "struct" prefix
-            "FILE" | "fd_set" | "Dl_info" | "DIR" => ty.to_string(),
+            "FILE" | "fd_set" | "Dl_info" | "DIR" | "Elf32_Phdr"
+            | "Elf64_Phdr" => ty.to_string(),
 
             // FIXME: https://github.com/rust-lang/libc/issues/1273
             "sighandler_t" => "sig_t".to_string(),
@@ -1909,6 +1936,10 @@ fn test_freebsd(target: &str) {
             // `void*`:
             ("stack_t", "ss_sp") if Some(10) == freebsd_ver => true,
 
+            // conflicting with `p_type` macro from <resolve.h>.
+            ("Elf32_Phdr", "p_type") => true,
+            ("Elf64_Phdr", "p_type") => true,
+
             _ => false,
         }
     });
diff --git a/src/unix/bsd/freebsdlike/freebsd/mod.rs b/src/unix/bsd/freebsdlike/freebsd/mod.rs
index bfd60636fefef018667171a6ce10cafe47a2c072..e65c048d6c5feee53ec54e9d42c72389143f0975 100644
--- a/src/unix/bsd/freebsdlike/freebsd/mod.rs
+++ b/src/unix/bsd/freebsdlike/freebsd/mod.rs
@@ -1502,7 +1502,7 @@ extern "C" {
     pub fn nmount(
         iov: *mut ::iovec,
         niov: ::c_uint,
-        flags: ::c_int
+        flags: ::c_int,
     ) -> ::c_int;
 }
 
diff --git a/src/unix/bsd/freebsdlike/mod.rs b/src/unix/bsd/freebsdlike/mod.rs
index 7bf9399d97f2651a0816bc445546f52970c7ced8..a9b0149a0abb6bfb41fbf5f5e004ff2c573fa5fa 100644
--- a/src/unix/bsd/freebsdlike/mod.rs
+++ b/src/unix/bsd/freebsdlike/mod.rs
@@ -14,6 +14,38 @@ pub type nl_item = ::c_int;
 pub type id_t = i64;
 pub type vm_size_t = ::uintptr_t;
 
+// elf.h
+
+pub type Elf32_Addr = u32;
+pub type Elf32_Half = u16;
+pub type Elf32_Lword = u64;
+pub type Elf32_Off = u32;
+pub type Elf32_Sword = i32;
+pub type Elf32_Word = u32;
+
+pub type Elf64_Addr = u64;
+pub type Elf64_Half = u16;
+pub type Elf64_Lword = u64;
+pub type Elf64_Off = u64;
+pub type Elf64_Sword = i32;
+pub type Elf64_Sxword = i64;
+pub type Elf64_Word = u32;
+pub type Elf64_Xword = u64;
+
+cfg_if! {
+    if #[cfg(target_pointer_width = "64")] {
+        type Elf_Addr = Elf64_Addr;
+        type Elf_Half = Elf64_Half;
+        type Elf_Phdr = Elf64_Phdr;
+    } else if #[cfg(target_pointer_width = "32")] {
+        type Elf_Addr = Elf32_Addr;
+        type Elf_Half = Elf32_Half;
+        type Elf_Phdr = Elf32_Phdr;
+    }
+}
+
+// link.h
+
 #[cfg_attr(feature = "extra_traits", derive(Debug))]
 pub enum timezone {}
 impl ::Copy for timezone {}
@@ -233,6 +265,43 @@ s! {
         pub piod_addr: *mut ::c_void,
         pub piod_len: ::size_t,
     }
+
+    // elf.h
+
+    pub struct Elf32_Phdr {
+        pub p_type: Elf32_Word,
+        pub p_offset: Elf32_Off,
+        pub p_vaddr: Elf32_Addr,
+        pub p_paddr: Elf32_Addr,
+        pub p_filesz: Elf32_Word,
+        pub p_memsz: Elf32_Word,
+        pub p_flags: Elf32_Word,
+        pub p_align: Elf32_Word,
+    }
+
+    pub struct Elf64_Phdr {
+        pub p_type: Elf64_Word,
+        pub p_flags: Elf64_Word,
+        pub p_offset: Elf64_Off,
+        pub p_vaddr: Elf64_Addr,
+        pub p_paddr: Elf64_Addr,
+        pub p_filesz: Elf64_Xword,
+        pub p_memsz: Elf64_Xword,
+        pub p_align: Elf64_Xword,
+    }
+
+    // link.h
+
+    pub struct dl_phdr_info {
+        pub dlpi_addr: Elf_Addr,
+        pub dlpi_name: *const ::c_char,
+        pub dlpi_phdr: *const Elf_Phdr,
+        pub dlpi_phnum: Elf_Half,
+        pub dlpi_adds: ::c_ulonglong,
+        pub dlpi_subs: ::c_ulonglong,
+        pub dlpi_tls_modid: usize,
+        pub dlpi_tls_data: *mut ::c_void,
+    }
 }
 
 s_no_extra_traits! {
@@ -1514,6 +1583,18 @@ extern "C" {
 
     pub fn ntp_adjtime(buf: *mut timex) -> ::c_int;
     pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int;
+
+    // #include <link.h>
+    pub fn dl_iterate_phdr(
+        callback: ::Option<
+            unsafe extern "C" fn(
+                info: *mut dl_phdr_info,
+                size: usize,
+                data: *mut ::c_void,
+            ) -> ::c_int,
+        >,
+        data: *mut ::c_void,
+    ) -> ::c_int;
 }
 
 #[link(name = "rt")]
diff --git a/src/unix/bsd/netbsdlike/netbsd/mod.rs b/src/unix/bsd/netbsdlike/netbsd/mod.rs
index ee9cda2487cdc8a24ce42fe8e5ce808d962e0377..4b7dbafc144c4aaa8d1e2f20613b0d3d7bff5cee 100644
--- a/src/unix/bsd/netbsdlike/netbsd/mod.rs
+++ b/src/unix/bsd/netbsdlike/netbsd/mod.rs
@@ -11,6 +11,36 @@ pub type vm_size_t = ::uintptr_t;
 pub type lwpid_t = ::c_uint;
 pub type shmatt_t = ::c_uint;
 
+// elf.h
+
+pub type Elf32_Addr = u32;
+pub type Elf32_Half = u16;
+pub type Elf32_Lword = u64;
+pub type Elf32_Off = u32;
+pub type Elf32_Sword = i32;
+pub type Elf32_Word = u32;
+
+pub type Elf64_Addr = u64;
+pub type Elf64_Half = u16;
+pub type Elf64_Lword = u64;
+pub type Elf64_Off = u64;
+pub type Elf64_Sword = i32;
+pub type Elf64_Sxword = i64;
+pub type Elf64_Word = u32;
+pub type Elf64_Xword = u64;
+
+cfg_if! {
+    if #[cfg(target_pointer_width = "64")] {
+        type Elf_Addr = Elf64_Addr;
+        type Elf_Half = Elf64_Half;
+        type Elf_Phdr = Elf64_Phdr;
+    } else if #[cfg(target_pointer_width = "32")] {
+        type Elf_Addr = Elf32_Addr;
+        type Elf_Half = Elf32_Half;
+        type Elf_Phdr = Elf32_Phdr;
+    }
+}
+
 impl siginfo_t {
     pub unsafe fn si_value(&self) -> ::sigval {
         #[repr(C)]
@@ -341,6 +371,42 @@ s! {
         pub time_state: ::c_int,
     }
 
+    // elf.h
+
+    pub struct Elf32_Phdr {
+        pub p_type: Elf32_Word,
+        pub p_offset: Elf32_Off,
+        pub p_vaddr: Elf32_Addr,
+        pub p_paddr: Elf32_Addr,
+        pub p_filesz: Elf32_Word,
+        pub p_memsz: Elf32_Word,
+        pub p_flags: Elf32_Word,
+        pub p_align: Elf32_Word,
+    }
+
+    pub struct Elf64_Phdr {
+        pub p_type: Elf64_Word,
+        pub p_flags: Elf64_Word,
+        pub p_offset: Elf64_Off,
+        pub p_vaddr: Elf64_Addr,
+        pub p_paddr: Elf64_Addr,
+        pub p_filesz: Elf64_Xword,
+        pub p_memsz: Elf64_Xword,
+        pub p_align: Elf64_Xword,
+    }
+
+    // link.h
+
+    pub struct dl_phdr_info {
+        pub dlpi_addr: Elf_Addr,
+        pub dlpi_name: *const ::c_char,
+        pub dlpi_phdr: *const Elf_Phdr,
+        pub dlpi_phnum: Elf_Half,
+        pub dlpi_adds: ::c_ulonglong,
+        pub dlpi_subs: ::c_ulonglong,
+        pub dlpi_tls_modid: usize,
+        pub dlpi_tls_data: *mut ::c_void,
+    }
 }
 
 s_no_extra_traits! {
@@ -2002,6 +2068,19 @@ extern "C" {
         needle: *const ::c_void,
         needlelen: ::size_t,
     ) -> *mut ::c_void;
+
+    // link.h
+
+    pub fn dl_iterate_phdr(
+        callback: ::Option<
+            unsafe extern "C" fn(
+                info: *mut dl_phdr_info,
+                size: usize,
+                data: *mut ::c_void,
+            ) -> ::c_int,
+        >,
+        data: *mut ::c_void,
+    ) -> ::c_int;
 }
 
 #[link(name = "util")]
diff --git a/src/unix/bsd/netbsdlike/openbsd/mod.rs b/src/unix/bsd/netbsdlike/openbsd/mod.rs
index 4fe134eec48e5ae6e8199a1e598e1df02a5145c7..c46f3a41be3241ab0df0bc83a748f65920912a2e 100644
--- a/src/unix/bsd/netbsdlike/openbsd/mod.rs
+++ b/src/unix/bsd/netbsdlike/openbsd/mod.rs
@@ -16,6 +16,36 @@ pub type pthread_rwlock_t = *mut ::c_void;
 pub type pthread_rwlockattr_t = *mut ::c_void;
 pub type caddr_t = *mut ::c_char;
 
+// elf.h
+
+pub type Elf32_Addr = u32;
+pub type Elf32_Half = u16;
+pub type Elf32_Lword = u64;
+pub type Elf32_Off = u32;
+pub type Elf32_Sword = i32;
+pub type Elf32_Word = u32;
+
+pub type Elf64_Addr = u64;
+pub type Elf64_Half = u16;
+pub type Elf64_Lword = u64;
+pub type Elf64_Off = u64;
+pub type Elf64_Sword = i32;
+pub type Elf64_Sxword = i64;
+pub type Elf64_Word = u32;
+pub type Elf64_Xword = u64;
+
+cfg_if! {
+    if #[cfg(target_pointer_width = "64")] {
+        type Elf_Addr = Elf64_Addr;
+        type Elf_Half = Elf64_Half;
+        type Elf_Phdr = Elf64_Phdr;
+    } else if #[cfg(target_pointer_width = "32")] {
+        type Elf_Addr = Elf32_Addr;
+        type Elf_Half = Elf32_Half;
+        type Elf_Phdr = Elf32_Phdr;
+    }
+}
+
 s! {
     pub struct glob_t {
         pub gl_pathc:   ::size_t,
@@ -321,6 +351,38 @@ s! {
         __shm_ctimensec: c_long,
         pub shm_internal: *mut ::c_void,
     }
+
+    // elf.h
+    pub struct Elf32_Phdr {
+        pub p_type: Elf32_Word,
+        pub p_offset: Elf32_Off,
+        pub p_vaddr: Elf32_Addr,
+        pub p_paddr: Elf32_Addr,
+        pub p_filesz: Elf32_Word,
+        pub p_memsz: Elf32_Word,
+        pub p_flags: Elf32_Word,
+        pub p_align: Elf32_Word,
+    }
+
+    pub struct Elf64_Phdr {
+        pub p_type: Elf64_Word,
+        pub p_flags: Elf64_Word,
+        pub p_offset: Elf64_Off,
+        pub p_vaddr: Elf64_Addr,
+        pub p_paddr: Elf64_Addr,
+        pub p_filesz: Elf64_Xword,
+        pub p_memsz: Elf64_Xword,
+        pub p_align: Elf64_Xword,
+    }
+
+    // link.h
+
+    pub struct dl_phdr_info {
+        pub dlpi_addr: Elf_Addr,
+        pub dlpi_name: *const ::c_char,
+        pub dlpi_phdr: *const Elf_Phdr,
+        pub dlpi_phnum: Elf_Half,
+    }
 }
 
 impl siginfo_t {
@@ -1482,6 +1544,17 @@ extern "C" {
         needle: *const ::c_void,
         needlelen: ::size_t,
     ) -> *mut ::c_void;
+    // #include <link.h>
+    pub fn dl_iterate_phdr(
+        callback: ::Option<
+            unsafe extern "C" fn(
+                info: *mut dl_phdr_info,
+                size: usize,
+                data: *mut ::c_void,
+            ) -> ::c_int,
+        >,
+        data: *mut ::c_void,
+    ) -> ::c_int;
 }
 
 cfg_if! {