Fix /proc/<PID>/maps output for PEB and TEBs on W10 1511

* fhandler_process.cc (heap_info::fill_if_match): Return NULL, not 0.
        (thread_info::fill_if_match): Ditto.
        (thread_info::fill_if_match): New method to extract TEB info from
        PEB/TEB region since W10 1511.
        (format_process_maps): Drop outdated FIXME comment.  Add code to handle
        PEB/TEB region since W10 1511.
        * mmap.cc (posix_madvise): Align comment to new W10 1511 version.
        * wincap.h (wincaps::has_new_pebteb_region): New element.
        * wincap.cc: Implement above element throughout.
        (wincap_10_1511): New global wincaps to support Windows 10 since 1511.
        (wincapc::init): Use wincap_10_1511 for W10 builds >= 10586.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2015-12-03 13:33:43 +01:00
parent 8a14e51901
commit f1ed5bfa83
5 changed files with 113 additions and 10 deletions

View File

@ -1,3 +1,17 @@
2015-12-03 Corinna Vinschen <corinna@vinschen.de>
* fhandler_process.cc (heap_info::fill_if_match): Return NULL, not 0.
(thread_info::fill_if_match): Ditto.
(thread_info::fill_if_match): New method to extract TEB info from
PEB/TEB region since W10 1511.
(format_process_maps): Drop outdated FIXME comment. Add code to handle
PEB/TEB region since W10 1511.
* mmap.cc (posix_madvise): Align comment to new W10 1511 version.
* wincap.h (wincaps::has_new_pebteb_region): New element.
* wincap.cc: Implement above element throughout.
(wincap_10_1511): New global wincaps to support Windows 10 since 1511.
(wincapc::init): Use wincap_10_1511 for W10 builds >= 10586.
2015-12-03 Corinna Vinschen <corinna@vinschen.de>
x86_64 only:

View File

@ -648,7 +648,7 @@ struct heap_info
stpcpy (p, "]");
return dest;
}
return 0;
return NULL;
}
~heap_info ()
@ -769,7 +769,21 @@ struct thread_info
stpcpy (p, "]");
return dest;
}
return 0;
return NULL;
}
char *fill_if_match (char *start, char *end, ULONG type, char *dest)
{
for (region *r = regions; r; r = r->next)
if (r->teb && start <= r->start && r->end <= end)
{
char *p = dest + __small_sprintf (dest, "[teb (tid %ld)",
r->thread_id);
if (type & MEM_MAPPED)
p = stpcpy (p, " shared");
stpcpy (p, "]");
return dest;
}
return NULL;
}
~thread_info ()
@ -847,12 +861,7 @@ format_process_maps (void *data, char *&destbuf)
/* Iterate over each VM region in the address space, coalescing
memory regions with the same permissions. Once we run out, do one
last_pass to trigger output of the last accumulated region.
FIXME: 32 bit processes can't get address information beyond the
32 bit address space from 64 bit processes. We have to run
this functionality in the target process, if the target
process is 64 bit and our own process is 32 bit. */
last_pass to trigger output of the last accumulated region. */
for (char *i = 0;
VirtualQueryEx (proc, i, &mb, sizeof(mb)) || (1 == ++last_pass);
i = cur.rend)
@ -899,6 +908,33 @@ format_process_maps (void *data, char *&destbuf)
cur.rend = next.rend; /* merge with previous */
else
{
char *peb_teb_end = NULL;
peb_teb_rinse_repeat:
/* Starting with W10 1511, PEB and TEBs don't get allocated
separately. Rather they are created in a single region. Examine
the region starting at the PEB address page-wise. */
if (wincap.has_new_pebteb_region ())
{
if (!newbase && cur.rbase == (char *) peb)
{
strcpy (posix_modname, "[peb]");
peb_teb_end = cur.rend;
cur.rend = cur.rbase + wincap.page_size ();
}
else if (peb_teb_end)
{
posix_modname[0] = '\0';
if (!threads.fill_if_match (cur.rbase, cur.rend,
mb.Type, posix_modname))
do
{
cur.rend += wincap.page_size ();
}
while (!threads.fill_if_match (cur.rbase, cur.rend,
mb.Type, posix_modname)
&& cur.rend < peb_teb_end);
}
}
/* output the current region if it's "interesting". */
if (cur.a.word)
{
@ -919,6 +955,14 @@ format_process_maps (void *data, char *&destbuf)
len += written;
len += __small_sprintf (destbuf + len, "%s\n", posix_modname);
}
if (peb_teb_end)
{
cur.rbase = cur.rend;
cur.rend += wincap.page_size ();
if (cur.rbase < peb_teb_end)
goto peb_teb_rinse_repeat;
}
/* start of a new region (but possibly still the same allocation). */
cur = next;
/* if a new allocation, figure out what kind it is. */

View File

@ -1578,7 +1578,7 @@ posix_madvise (void *addr, size_t len, int advice)
/* FIXME 2015-08-27: On W10 build 10240 under WOW64,
PrefetchVirtualMemory always returns ERROR_INVALID_PARAMETER
for some reason. If we're running on W10 WOW64, ignore this
error for now. There's an open case at Microsoft for this. */
error. This has been fixed in W10 1511. */
if (!wincap.has_broken_prefetchvm ()
|| GetLastError () != ERROR_INVALID_PARAMETER)
ret = EINVAL;

View File

@ -51,6 +51,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:false,
has_broken_prefetchvm:false,
has_new_pebteb_region:false,
};
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -84,6 +85,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_rtl_query_process_debug_information:true,
has_processor_groups:false,
has_broken_prefetchvm:false,
has_new_pebteb_region:false,
};
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -117,6 +119,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:false,
has_broken_prefetchvm:false,
has_new_pebteb_region:false,
};
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -150,6 +153,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:false,
has_new_pebteb_region:false,
};
wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -183,6 +187,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:false,
has_new_pebteb_region:false,
};
wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -216,6 +221,41 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:true,
has_new_pebteb_region:false,
};
wincaps wincap_10_1511 __attribute__((section (".cygwin_dll_common"), shared)) = {
def_guard_pages:2,
max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE,
is_server:false,
has_mandatory_integrity_control:true,
needs_count_in_si_lpres2:false,
has_recycle_dot_bin:true,
has_gaa_on_link_prefix:true,
has_gaa_largeaddress_bug:false,
supports_all_posix_ai_flags:true,
has_restricted_stack_args:false,
has_transactions:true,
has_sendmsg:true,
has_broken_udf:false,
has_broken_alloc_console:true,
has_always_all_codepages:true,
has_localenames:true,
has_fast_cwd:true,
has_restricted_raw_disk_access:true,
use_dont_resolve_hack:false,
has_console_logon_sid:true,
wow64_has_secondary_stack:false,
has_program_compatibility_assistant:true,
has_pipe_reject_remote_clients:true,
terminate_thread_frees_stack:true,
has_precise_system_time:true,
has_microsoft_accounts:true,
has_set_thread_stack_guarantee:true,
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:false,
has_new_pebteb_region:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
@ -263,7 +303,10 @@ wincapc::init ()
break;
case 10:
default:
caps = &wincap_10;
if (version.dwBuildNumber >= 10586)
caps = &wincap_10_1511;
else
caps = &wincap_10;
break;
}

View File

@ -44,6 +44,7 @@ struct wincaps
unsigned has_broken_rtl_query_process_debug_information : 1;
unsigned has_processor_groups : 1;
unsigned has_broken_prefetchvm : 1;
unsigned has_new_pebteb_region : 1;
};
class wincapc
@ -102,6 +103,7 @@ public:
bool IMPLEMENT (has_broken_rtl_query_process_debug_information)
bool IMPLEMENT (has_processor_groups)
bool IMPLEMENT (has_broken_prefetchvm)
bool IMPLEMENT (has_new_pebteb_region)
#undef IMPLEMENT
};