Hi,

Needs an RB_GENERATE, see devel/libgtop2/files/procmap.c used this at
end of file. Adding this builds, but I get a Seg fault when attempting
running built lsof on amd64.

/*
 * Don't implement address comparison.
 */
static __inline int
no_impl(void *p, void *q)
{
        abort(); /* Should not be called. */
        return 0;
}


RB_GENERATE(uvm_map_addr, vm_map_entry, daddrs.addr_entry, no_impl);


Regards

Nigel Taylor

On 06/03/11 18:41, Stuart Henderson wrote:
> In gmane.os.openbsd.misc, you wrote:
>> On Fri, Jun 03, 2011 at 03:27:37PM +0200, David Coppa wrote:
>>> On Thu, Jun 2, 2011 at 7:14 PM, Antoine Jacoutot <[email protected]> 
>>> wrote:
>>>
>>>> I guess you are not current enough to build lsof.
>>>
>>>>> dproc.c: In function 'process_text':
>>>>> dproc.c:539: error: 'struct vm_map' has no member named 'nentries'
>>>>> dproc.c:545: error: 'struct vm_map' has no member named 'header'
>>>>> dproc.c:547: error: 'struct vm_map_entry' has no member named 'next'
>>>>> *** Error code 1
>>>
>>> I'm current (done a "make build" this morning) and I confirm lsof is
>>> broken due to vmmap.
>>>
>>> Ariane, please, can you help shedding some light?
>>
>> This is the same as procmap (from base) and libgtop (from ports) do.
>> They traversed the map using a linked list (in the old allocator this
>> list existed). The new allocator only has a tree.
>>
>> The easiest way to traverse a map from userspace is to recreate the tree
>> in userspace, then use RB_FOREACH to traverse it. This is what is done
>> to make libgtop2 work properly.
>> See /usr/ports/devel/libgtop2/files/procmap.c for sample code; the
>> load_vmmap_entries and unload_vmmap_entries code can be copied verbatim
>> and adapted to lsofs idea of kvm_read.
>>
>>         RB_INIT(&root);
>>         nentries = load_vmmap_entries(server,
>>             (unsigned long) RB_ROOT(&vmspace.vm_map.addr),
>>             &RB_ROOT(&root), NULL);
>>         if (nentries == -1) {
>>                 unload_vmmap_entries(RB_ROOT(&root));
>>                 glibtop_error_io_r (server, "kvm_read (entry)");
>>         }
>>
>>         RB_FOREACH(entry, uvm_map_addr, &root) {
>>                 /*
>>                  * funky code goes here
>>                  */
>>         }
>>
>>         unload_vmmap_entries(RB_ROOT(&root));
>>
>> The load_vmmap_entries function performs copy from kernel to userland.
>> The unload_vmmap_entries is a recursive free() (and must be called if
>> the copy fails).
>> -- 
>> Ariane
>>
>>
> 
> Trying the diff below but I'm getting this when linking. Any clues
> as to what I'm missing?
> 
> ./lib/liblsof.a(dvch.o)(.text+0x4fe): In function `dcpath':
> : warning: strcpy() is almost always misused, please use strlcpy()
> dproc.o(.text+0x531): In function `gather_proc_info':
> : undefined reference to `uvm_map_addr_RB_MINMAX'
> dproc.o(.text+0x64e): In function `gather_proc_info':
> : undefined reference to `uvm_map_addr_RB_NEXT'
> collect2: ld returned 1 exit status
> *** Error code 1
> 
> $OpenBSD$
> --- dialects/n+obsd/dproc.c.orig      Wed May 11 13:54:00 2005
> +++ dialects/n+obsd/dproc.c   Fri Jun  3 18:35:26 2011
> @@ -93,7 +93,88 @@ ckkv(d, er, ev, ea)
>  }
>  
>  
> +
>  /*
> + * Download vmmap_entries from the kernel into our address space.
> + * We fix up the addr tree while downloading.
> + *
> + * Returns: the size of the tree on succes, or -1 on failure.
> + * On failure, *rptr needs to be passed to unload_vmmap_entries to free
> + * the lot.
> + */
> +ssize_t
> +load_vmmap_entries(unsigned long kptr,
> +    struct vm_map_entry **rptr, struct vm_map_entry *parent)
> +{
> +     struct vm_map_entry *entry;
> +     unsigned long left_kptr, right_kptr;
> +     ssize_t left_sz;
> +     ssize_t right_sz;
> +
> +     if (kptr == 0)
> +             return 0;
> +
> +     /* Need space. */
> +     entry = malloc(sizeof(*entry));
> +     if (entry == NULL)
> +             return -1;
> +
> +     /* Download entry at kptr. */
> +     if (kvm_read (Kd, kptr,
> +         (char *)entry, sizeof(*entry)) != sizeof(*entry)) {
> +             free(entry);
> +             return -1;
> +     }
> +
> +     /*
> +      * Update addr pointers to have sane values in this address space.
> +      * We save the kernel pointers in {left,right}_kptr, so we have them
> +      * available to download children.
> +      */
> +     left_kptr = (unsigned long) RB_LEFT(entry, daddrs.addr_entry);
> +     right_kptr = (unsigned long) RB_RIGHT(entry, daddrs.addr_entry);
> +     RB_LEFT(entry, daddrs.addr_entry) =
> +         RB_RIGHT(entry, daddrs.addr_entry) = NULL;
> +     /* Fill in parent pointer. */
> +     RB_PARENT(entry, daddrs.addr_entry) = parent;
> +
> +     /*
> +      * Consistent state reached, fill in *rptr.
> +      */
> +     *rptr = entry;
> +
> +     /*
> +      * Download left, right.
> +      * On failure, our map is in a state that can be handled by
> +      * unload_vmmap_entries.
> +      */
> +     left_sz = load_vmmap_entries(left_kptr,
> +         &RB_LEFT(entry, daddrs.addr_entry), entry);
> +     if (left_sz == -1)
> +             return -1;
> +     right_sz = load_vmmap_entries(right_kptr,
> +         &RB_RIGHT(entry, daddrs.addr_entry), entry);
> +     if (right_sz == -1)
> +             return -1;
> +
> +     return 1 + left_sz + right_sz;
> +}
> +
> +/*
> + * Free the vmmap entries in the given tree.
> + */
> +void
> +unload_vmmap_entries(struct vm_map_entry *entry)
> +{
> +     if (entry == NULL)
> +             return;
> +
> +     unload_vmmap_entries(RB_LEFT(entry, daddrs.addr_entry));
> +     unload_vmmap_entries(RB_RIGHT(entry, daddrs.addr_entry));
> +     free(entry);
> +}
> +
> +/*
>   * enter_vn_text() - enter a vnode text reference
>   */
>  
> @@ -515,13 +596,10 @@ process_text(vm)
>       KA_T ka;
>       int n = 0;
>       struct vm_map_entry vmme, *e;
> +     struct uvm_map_addr root;
>       struct vmspace vmsp;
> +     ssize_t nentries;
>  
> -#if  !defined(UVM)
> -     struct pager_struct pg;
> -     struct vm_object vmo;
> -#endif       /* !defined(UVM) */
> -
>  /*
>   * Read the vmspace structure for the process.
>   */
> @@ -531,54 +609,25 @@ process_text(vm)
>   * Read the vm_map structure.  Search its vm_map_entry structure list.
>   */
>  
> -#if  !defined(UVM)
> -     if (!vmsp.vm_map.is_main_map)
> -         return;
> -#endif       /* !defined(UVM) */
> +     RB_INIT(&root);
> +     nentries = load_vmmap_entries(
> +         (unsigned long) RB_ROOT(&vmsp.vm_map.addr),
> +         &RB_ROOT(&root), NULL);
> +     if (nentries == -1) {
> +             unload_vmmap_entries(RB_ROOT(&root));
> +             (void) fprintf(stderr, "%s: kvm_read (entry)", Pn);
> +             Exit(1);
> +     }
>  
> -     for (i = 0; i < vmsp.vm_map.nentries; i++) {
> -
> -     /*
> -      * Read the next vm_map_entry.
> -      */
> -         if (!i)
> -             e = &vmsp.vm_map.header;
> -         else {
> -             if (!(ka = (KA_T)e->next))
> -                 return;
> -             e = &vmme;
> +     RB_FOREACH(e, uvm_map_addr, &root) {
>               if (kread(ka, (char *)e, sizeof(vmme)))
>                   return;
> -         }
>  
> -#if  defined(UVM)
>       /*
>        * Process the uvm_obj pointer of a UVM map entry with a UVM_ET_OBJ
>        * type as a vnode pointer.
>        */
>           if ((e->etype > UVM_ET_OBJ) && e->object.uvm_obj)
>               (void) enter_vn_text((KA_T)e->object.uvm_obj, &n);
> -#else        /* !defined(UVM) */
> -     /*
> -      * Read the map entry's object and the object's shadow.
> -      * Look for a PG_VNODE pager handle.
> -      */
> -         if (e->is_a_map || e->is_sub_map)
> -             continue;
> -         for (j = 0, ka = (KA_T)e->object.vm_object;
> -              j < 2 && ka;
> -              j++, ka = (KA_T)vmo.shadow)
> -         {
> -             if (kread(ka, (char *)&vmo, sizeof(vmo)))
> -                 break;
> -             if (!(ka = (KA_T)vmo.pager)
> -             ||   kread(ka, (char *)&pg, sizeof(pg)))
> -                 continue;
> -             if (!pg.pg_handle || pg.pg_type != PG_VNODE)
> -                 continue;
> -             (void) enter_vn_text((KA_T)pg.pg_handle, &n);
> -         }
> -#endif       /* defined(UVM) */
> -
>       }
>  }

Reply via email to