Fix thinko in /proc/<PID>/maps TEB detection on W10 1511
* fhandler_process.cc (thread_info::thread_info): Accommodate the fact that TEBs take two pages. (thread_info::fill_if_match): Rewrite the method for post W10 1511 TEB detection. (format_process_maps): Add a state member to region. Fix the code to handle PEB/TEB region since W10 1511. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
f1ed5bfa83
commit
8f4da28eb6
@ -1,3 +1,12 @@
|
|||||||
|
2015-12-03 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler_process.cc (thread_info::thread_info): Accommodate the fact
|
||||||
|
that TEBs take two pages.
|
||||||
|
(thread_info::fill_if_match): Rewrite the method for post W10 1511 TEB
|
||||||
|
detection.
|
||||||
|
(format_process_maps): Add a state member to region. Fix the code
|
||||||
|
to handle PEB/TEB region since W10 1511.
|
||||||
|
|
||||||
2015-12-03 Corinna Vinschen <corinna@vinschen.de>
|
2015-12-03 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* fhandler_process.cc (heap_info::fill_if_match): Return NULL, not 0.
|
* fhandler_process.cc (heap_info::fill_if_match): Return NULL, not 0.
|
||||||
|
@ -731,7 +731,8 @@ struct thread_info
|
|||||||
{
|
{
|
||||||
*r = (region) { regions, (ULONG) (ULONG_PTR) thread[i].ClientId.UniqueThread,
|
*r = (region) { regions, (ULONG) (ULONG_PTR) thread[i].ClientId.UniqueThread,
|
||||||
(char *) tbi.TebBaseAddress,
|
(char *) tbi.TebBaseAddress,
|
||||||
(char *) tbi.TebBaseAddress + wincap.page_size (),
|
(char *) tbi.TebBaseAddress
|
||||||
|
+ 2 * wincap.page_size (),
|
||||||
true };
|
true };
|
||||||
regions = r;
|
regions = r;
|
||||||
}
|
}
|
||||||
@ -771,17 +772,14 @@ struct thread_info
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char *fill_if_match (char *start, char *end, ULONG type, char *dest)
|
/* Helper to look for TEBs inside single allocated region since W10 1511. */
|
||||||
|
char *fill_if_match (char *start, char *dest)
|
||||||
{
|
{
|
||||||
for (region *r = regions; r; r = r->next)
|
for (region *r = regions; r; r = r->next)
|
||||||
if (r->teb && start <= r->start && r->end <= end)
|
if (r->teb && start == r->start)
|
||||||
{
|
{
|
||||||
char *p = dest + __small_sprintf (dest, "[teb (tid %ld)",
|
__small_sprintf (dest, "[teb (tid %ld)]", r->thread_id);
|
||||||
r->thread_id);
|
return r->end;
|
||||||
if (type & MEM_MAPPED)
|
|
||||||
p = stpcpy (p, " shared");
|
|
||||||
stpcpy (p, "]");
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -839,6 +837,7 @@ format_process_maps (void *data, char *&destbuf)
|
|||||||
char *abase;
|
char *abase;
|
||||||
char *rbase;
|
char *rbase;
|
||||||
char *rend;
|
char *rend;
|
||||||
|
DWORD state;
|
||||||
} cur = {{{'\0'}}, (char *)1, 0, 0};
|
} cur = {{{'\0'}}, (char *)1, 0, 0};
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mb;
|
MEMORY_BASIC_INFORMATION mb;
|
||||||
@ -852,6 +851,7 @@ format_process_maps (void *data, char *&destbuf)
|
|||||||
PMEMORY_SECTION_NAME msi = (PMEMORY_SECTION_NAME) tp.w_get ();
|
PMEMORY_SECTION_NAME msi = (PMEMORY_SECTION_NAME) tp.w_get ();
|
||||||
char *posix_modname = tp.c_get ();
|
char *posix_modname = tp.c_get ();
|
||||||
size_t maxsize = 0;
|
size_t maxsize = 0;
|
||||||
|
char *peb_teb_abase = NULL;
|
||||||
|
|
||||||
if (destbuf)
|
if (destbuf)
|
||||||
{
|
{
|
||||||
@ -897,7 +897,8 @@ format_process_maps (void *data, char *&destbuf)
|
|||||||
region next = { a,
|
region next = { a,
|
||||||
(char *) mb.AllocationBase,
|
(char *) mb.AllocationBase,
|
||||||
(char *) mb.BaseAddress,
|
(char *) mb.BaseAddress,
|
||||||
(char *) mb.BaseAddress+mb.RegionSize
|
(char *) mb.BaseAddress+mb.RegionSize,
|
||||||
|
mb.State
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Windows permissions are more fine-grained than the unix rwxp,
|
/* Windows permissions are more fine-grained than the unix rwxp,
|
||||||
@ -915,24 +916,48 @@ peb_teb_rinse_repeat:
|
|||||||
the region starting at the PEB address page-wise. */
|
the region starting at the PEB address page-wise. */
|
||||||
if (wincap.has_new_pebteb_region ())
|
if (wincap.has_new_pebteb_region ())
|
||||||
{
|
{
|
||||||
if (!newbase && cur.rbase == (char *) peb)
|
if (peb_teb_abase && !peb_teb_end && cur.abase == peb_teb_abase)
|
||||||
{
|
|
||||||
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';
|
posix_modname[0] = '\0';
|
||||||
if (!threads.fill_if_match (cur.rbase, cur.rend,
|
peb_teb_end = cur.rend;
|
||||||
mb.Type, posix_modname))
|
if (cur.state == MEM_COMMIT)
|
||||||
do
|
cur.rend = cur.rbase + wincap.page_size ();
|
||||||
{
|
}
|
||||||
cur.rend += wincap.page_size ();
|
if (cur.state == MEM_COMMIT)
|
||||||
}
|
{
|
||||||
while (!threads.fill_if_match (cur.rbase, cur.rend,
|
if (!peb_teb_abase && cur.rbase == (char *) peb)
|
||||||
mb.Type, posix_modname)
|
{
|
||||||
&& cur.rend < peb_teb_end);
|
peb_teb_abase = cur.abase;
|
||||||
|
peb_teb_end = cur.rend;
|
||||||
|
cur.rend = cur.rbase + wincap.page_size ();
|
||||||
|
strcpy (posix_modname, "[peb]");
|
||||||
|
}
|
||||||
|
else if (peb_teb_end)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
posix_modname[0] = '\0';
|
||||||
|
end = threads.fill_if_match (cur.rbase, posix_modname);
|
||||||
|
|
||||||
|
if (end)
|
||||||
|
cur.rend = end;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *base = cur.rbase;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base += wincap.page_size ();
|
||||||
|
}
|
||||||
|
while (!threads.fill_if_match (base, posix_modname)
|
||||||
|
&& base < peb_teb_end);
|
||||||
|
if (posix_modname[0])
|
||||||
|
{
|
||||||
|
posix_modname[0] = '\0';
|
||||||
|
cur.rend = base;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cur.rend = peb_teb_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* output the current region if it's "interesting". */
|
/* output the current region if it's "interesting". */
|
||||||
@ -956,7 +981,7 @@ peb_teb_rinse_repeat:
|
|||||||
len += __small_sprintf (destbuf + len, "%s\n", posix_modname);
|
len += __small_sprintf (destbuf + len, "%s\n", posix_modname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peb_teb_end)
|
if (peb_teb_end && cur.state == MEM_COMMIT)
|
||||||
{
|
{
|
||||||
cur.rbase = cur.rend;
|
cur.rbase = cur.rend;
|
||||||
cur.rend += wincap.page_size ();
|
cur.rend += wincap.page_size ();
|
||||||
@ -966,7 +991,7 @@ peb_teb_rinse_repeat:
|
|||||||
/* start of a new region (but possibly still the same allocation). */
|
/* start of a new region (but possibly still the same allocation). */
|
||||||
cur = next;
|
cur = next;
|
||||||
/* if a new allocation, figure out what kind it is. */
|
/* if a new allocation, figure out what kind it is. */
|
||||||
if (newbase && !last_pass && mb.State != MEM_FREE)
|
if (newbase && !last_pass && cur.state != MEM_FREE)
|
||||||
{
|
{
|
||||||
/* If the return length pointer is missing, NtQueryVirtualMemory
|
/* If the return length pointer is missing, NtQueryVirtualMemory
|
||||||
returns with STATUS_ACCESS_VIOLATION on Windows 2000. */
|
returns with STATUS_ACCESS_VIOLATION on Windows 2000. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user