Mail Archives: djgpp-workers/2001/04/24/07:49:06
On Tue, 24 Apr 2001, Eli Zaretskii wrote:
> On Tue, 24 Apr 2001, Hans-Bernhard Broeker wrote:
> > So yes, it may well be that the code computing the actual size of
> > individual memory blocks is wrong, and thus tries to dump unmapped memory.
> > As far as I understand the code, it assumes that the whole address range
> > spanned __djgpp_memory_handle_list[] is mapped, up to
> > __djgpp_selector_limit, with no holes.
>
> I don't have the code handy: does each handle in the list specify its
> starting address and its size?
No. Quoting include/crt0.h:
typedef struct {
long handle;
unsigned address;
} __djgpp_sbrk_handle;
extern __djgpp_sbrk_handle __djgpp_memory_handle_list[256];
No size or end address is kept in the __djgpp_memory_handle_list. In
principle, the DPMI call mentioned below should be able to retreive the
size --- but it's a 1.0-only call :-(
For reference, here's the actual code from the core-dumping version of
dpmiexcp.c (slightly reindented for mailing):
static int make_decent_memory_block_list(void)
{
int i, j;
/* Get the base addresses, fill in a maximum size */
for (i = 0; (i < 256) && __djgpp_memory_handle_list[i].handle; i++)
{
mem_block_list[i].address = __djgpp_memory_handle_list[i].address;
mem_block_list[i].size = __djgpp_selector_limit + 1 -
mem_block_list[i].address;
mem_block_list[i].chunks = 0;
}
num_mem_blocks = i;
/* First reduce the sizes, using the fact that blocks can't overlap */
for (i = 0; i < num_mem_blocks; i++)
for (j = 0; j < num_mem_blocks; j++)
if (j != i)
if (mem_block_list[j].address > mem_block_list[i].address)
if (mem_block_list[j].address - mem_block_list[i].address <
mem_block_list[i].size)
mem_block_list[i].size = mem_block_list[j].address -
mem_block_list[i].address;
/* Now try the DPMI call; if it works, we can override the previous
* data; however, I have yet to find a DPMI server that supports it
*/
for (i = 0; i < num_mem_blocks; i++)
{
__dpmi_meminfo info = { 0, 0, 0 };
info.handle = __djgpp_memory_handle_list[i].handle;
if (__dpmi_get_memory_block_size_and_base (&info) != -1)
if (info.size) mem_block_list[i].size = info.size;
}
> If so, then why does the code need an
> assumption about the selector limit? If the handles don't specify their
> actual size, how in tghe world can _any_ code know which pages are and
> which aren't mapped into the program's address space?
Well --- maybe it can't, and that's the heart of our dilemma. Or maybe it
shouldn't have to, if we were to assume that the whole arena (from
0x000000000 to __djgpp_selector_limit) is always mapped, without holes.
> It is also possible that the bug is not in the core dumper, but in sbrk,
> where the handle list is maintained. Wrapping around unisgned values is
> notorious for concealing subtle bugs ;-)
IIRC, none of the linear address was in actual danger of wrapping around
at 4GB, here. DS base plus __djgpp_selector_limit was a lot smaller than
4GB. Somewhere safely between 0x8000000 and 0xA000000. So if there's any
overflow or wrapping, it'd have to be signed overflow (all relevant
addresses > INT_MAX, here).
> > It computes sizes of individual
> > blocks by their distance from the block with the next highest start
> > address.
>
> Is this the answer to my question above (about the use of selector
> limit)?
I think so, yes.
> If so, this computation needs to be refined. But the first
> thing I'd suggest to make sure is that the crashes all happen when a
> block whose ``next highest start address'' suffers from the 4GB
> wrap-around.
If I don't totally misremeber the figures, none of them did.
--
Hans-Bernhard Broeker (broeker AT physik DOT rwth-aachen DOT de)
Even if all the snow were burnt, ashes would remain.
- Raw text -