/* Once-per-image setup */
int mpidbg_init_per_image(mqs_image *image, const mqs_image_callbacks *icb,
                          struct mpidbg_handle_info_t *handle_types)
{
    char **message;
    mpi_image_info *i_info = 
        (mpi_image_info *) mqs_malloc(sizeof(mpi_image_info));
    printf("mpidbg_init_per_image\n");

    if (NULL == i_info) {
        printf("mpidbg_init_per_image: malloc failed!\n");
        return MPIDBG_ERR_NO_MEM;
    }

    memset((void *)i_info, 0, sizeof(mpi_image_info));
    /* Before we do *ANYTHING* else */
    i_info->image_callbacks = icb;

    /* Nothing extra (yet) */
    i_info->extra = NULL;

    /* Save the info */
    mqs_put_image_info(image, (mqs_image_info *)i_info);

    /* Fill in the OMPI type information */
    if (mqs_ok != ompi_fill_in_type_info(image, message)) {
        printf("mpidbg_init_per_image: failed to get all type info\n");
        return MPIDBG_ERR_NOT_SUPPORTED;
    }

    /* Fill in the handle_types struct with our types */
    /* JMS: "MPI_Aint" is a typedef -- is that enough?  (the actual
       type is a #define, so it's not easy to put into the
       mqs_find_type call as a string) */
    handle_types->hi_c_aint = mqs_find_type(image, "MPI_Aint", mqs_lang_c);
    /* JMS: these ompi types are just the "foo" types; but OMPI MPI
       types are all "foo*"'s -- is this right?  If this is wrong, I
       *suspect* that something like the following may be right:
       
       handle_types->hi_c_comm = mqs_find_type(image, "ompi_communicator_t*", mqs_lang_c);

       Need to confirm this with the DDT guys...
    */
    handle_types->hi_c_comm = i_info->ompi_communicator_t.type;
    handle_types->hi_c_datatype = i_info->ompi_datatype_t.type;
    handle_types->hi_c_errhandler = 
        mqs_find_type(image, "ompi_errhandler_t", mqs_lang_c);
    handle_types->hi_c_file = 
        mqs_find_type(image, "ompi_file_t", mqs_lang_c);
    handle_types->hi_c_group = i_info->ompi_group_t.type;
    handle_types->hi_c_info = 
        mqs_find_type(image, "ompi_info_t", mqs_lang_c);
    /* JMS: "MPI_Offset" is a typedef (see comment about MPI_Aint above) */
    handle_types->hi_c_offset =
        mqs_find_type(image, "MPI_Offset", mqs_lang_c);
    handle_types->hi_c_op = 
        mqs_find_type(image, "ompi_op_t", mqs_lang_c);
    handle_types->hi_c_request = i_info->ompi_request_t.type;
    handle_types->hi_c_status = i_info->ompi_status_public_t.type;
    handle_types->hi_c_win = 
        mqs_find_type(image, "ompi_win_t", mqs_lang_c);

    /* MPI::Aint is a typedef to MPI_Aint */
    handle_types->hi_cxx_aint = handle_types->hi_cxx_aint;
    handle_types->hi_cxx_comm =
        mqs_find_type(image, "MPI::Comm", mqs_lang_cplus);
    handle_types->hi_cxx_intracomm =
        mqs_find_type(image, "MPI::Intracomm", mqs_lang_cplus);
    handle_types->hi_cxx_intercomm =
        mqs_find_type(image, "MPI::Intercomm", mqs_lang_cplus);
    handle_types->hi_cxx_graphcomm =
        mqs_find_type(image, "MPI::Graphcomm", mqs_lang_cplus);
    handle_types->hi_cxx_cartcomm =
        mqs_find_type(image, "MPI::Cartcomm", mqs_lang_cplus);
    handle_types->hi_cxx_datatype =
        mqs_find_type(image, "MPI::Datatype", mqs_lang_cplus);
    handle_types->hi_cxx_errhandler =
        mqs_find_type(image, "MPI::Errhandler", mqs_lang_cplus);
    handle_types->hi_cxx_file =
        mqs_find_type(image, "MPI::File", mqs_lang_cplus);
    handle_types->hi_cxx_group =
        mqs_find_type(image, "MPI::Group", mqs_lang_cplus);
    handle_types->hi_cxx_info =
        mqs_find_type(image, "MPI::Info", mqs_lang_cplus);
    /* MPI::Offset is a typedef to MPI_Offset */
    handle_types->hi_cxx_offset = handle_types->hi_c_offset;
    handle_types->hi_cxx_op =
        mqs_find_type(image, "MPI::Op", mqs_lang_cplus);
    handle_types->hi_cxx_request =
        mqs_find_type(image, "MPI::Request", mqs_lang_cplus);
    handle_types->hi_cxx_prequest =
        mqs_find_type(image, "MPI::Prequest", mqs_lang_cplus);
    handle_types->hi_cxx_grequest =
        mqs_find_type(image, "MPI::Grequest", mqs_lang_cplus);
    handle_types->hi_cxx_status =
        mqs_find_type(image, "MPI::Status", mqs_lang_cplus);
    handle_types->hi_cxx_win =
        mqs_find_type(image, "MPI::Win", mqs_lang_cplus);

    /* Tell the debuger what capabilities we have */
    mpidbg_comm_capabilities = 
        MPIDBG_COMM_CAP_BASIC | 
        MPIDBG_COMM_CAP_STRING_NAMES | 
        MPIDBG_COMM_CAP_FREED_HANDLE | 
        MPIDBG_COMM_CAP_FREED_OBJECT;
    mpidbg_errhandler_capabilities =
        MPIDBG_ERRH_CAP_BASIC | 
        MPIDBG_ERRH_CAP_STRING_NAMES | 
        MPIDBG_ERRH_CAP_FREED_HANDLE | 
        MPIDBG_ERRH_CAP_FREED_OBJECT;
    mpidbg_request_capabilities = 
        MPIDBG_REQUEST_CAP_BASIC;
    mpidbg_status_capabilities = 
        MPIDBG_STATUS_CAP_BASIC;

    /* All done */
    printf("mpidbg_init_per_image: init succeeded -- ready!\n");
    return MPIDBG_SUCCESS;
}
/*
 * Open MPI use a bunch of lists in order to keep track of the
 * internal objects. We have to make sure we're able to find all of
 * them in the image and compute their ofset in order to be able to
 * parse them later.  We need to find the opal_list_item_t, the
 * opal_list_t, the ompi_free_list_item_t, and the ompi_free_list_t.
 *
 * Once we have these offsets, we should make sure that we have access
 * to all requests lists and types. We're looking here only at the
 * basic type for the requests as they hold all the information we
 * need to export to the debugger.
 */
int ompi_fill_in_type_info(mqs_image *image, char **message)
{
    char* missing_in_action;
    mpi_image_info * i_info = (mpi_image_info *)mqs_get_image_info (image);

    {
        mqs_type* qh_type = mqs_find_type( image, "opal_list_item_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_list_item_t";
            goto type_missing;
        }
        i_info->opal_list_item_t.type = qh_type;
        i_info->opal_list_item_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_list_item_t.offset.opal_list_next,
                          qh_type, opal_list_item_t, opal_list_next);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_list_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_list_t";
            goto type_missing;
        }
        i_info->opal_list_t.type = qh_type;
        i_info->opal_list_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_list_t.offset.opal_list_sentinel,
                          qh_type, opal_list_t, opal_list_sentinel);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_free_list_item_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_free_list_item_t";
            goto type_missing;
        }
        /* This is just an overloaded opal_list_item_t */
        i_info->ompi_free_list_item_t.type = qh_type;
        i_info->ompi_free_list_item_t.size = mqs_sizeof(qh_type);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_free_list_t", mqs_lang_c );

        if( !qh_type ) {
            missing_in_action = "ompi_free_list_t";
            goto type_missing;
        }

        i_info->ompi_free_list_t.type = qh_type;
        i_info->ompi_free_list_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_mpool,
                          qh_type, ompi_free_list_t, fl_mpool);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_allocations,
                          qh_type, ompi_free_list_t, fl_allocations); 
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_frag_class,
                          qh_type, ompi_free_list_t, fl_frag_class);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_frag_size,
                          qh_type, ompi_free_list_t, fl_frag_size);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_frag_alignment,
                          qh_type, ompi_free_list_t, fl_frag_alignment);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_max_to_alloc,
                          qh_type, ompi_free_list_t, fl_max_to_alloc);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_num_per_alloc,
                          qh_type, ompi_free_list_t, fl_num_per_alloc);
        ompi_field_offset(i_info->ompi_free_list_t.offset.fl_num_allocated,
                          qh_type, ompi_free_list_t, fl_num_allocated);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_hash_table_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_hash_table_t";
            goto type_missing;
        }
        i_info->opal_hash_table_t.type = qh_type;
        i_info->opal_hash_table_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_hash_table_t.offset.ht_table,
                          qh_type, opal_hash_table_t, ht_table);
        ompi_field_offset(i_info->opal_hash_table_t.offset.ht_table_size,
                          qh_type, opal_hash_table_t, ht_table_size);
        ompi_field_offset(i_info->opal_hash_table_t.offset.ht_size,
                          qh_type, opal_hash_table_t, ht_size);
        ompi_field_offset(i_info->opal_hash_table_t.offset.ht_mask,
                          qh_type, opal_hash_table_t, ht_mask);
    }
    /*
     * Now let's look for all types required for reading the requests.
     */
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_request_t";
            goto type_missing;
        }
        i_info->ompi_request_t.type = qh_type;
        i_info->ompi_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_request_t.offset.req_type,
                          qh_type, ompi_request_t, req_type);
        ompi_field_offset(i_info->ompi_request_t.offset.req_status,
                          qh_type, ompi_request_t, req_status);
        ompi_field_offset(i_info->ompi_request_t.offset.req_complete,
                          qh_type, ompi_request_t, req_complete);
        ompi_field_offset(i_info->ompi_request_t.offset.req_state,
                          qh_type, ompi_request_t, req_state);
        ompi_field_offset(i_info->ompi_request_t.offset.req_f_to_c_index,
                          qh_type, ompi_request_t, req_f_to_c_index);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_base_request_t";
            goto type_missing;
        }
        i_info->mca_pml_base_request_t.type = qh_type;
        i_info->mca_pml_base_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_addr,
                          qh_type, mca_pml_base_request_t, req_addr);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_count,
                          qh_type, mca_pml_base_request_t, req_count);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_peer,
                          qh_type, mca_pml_base_request_t, req_peer);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_tag,
                          qh_type, mca_pml_base_request_t, req_tag);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_comm,
                          qh_type, mca_pml_base_request_t, req_comm);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_datatype,
                          qh_type, mca_pml_base_request_t, req_datatype);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_proc,
                          qh_type, mca_pml_base_request_t, req_proc);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_sequence,
                          qh_type, mca_pml_base_request_t, req_sequence);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_type,
                          qh_type, mca_pml_base_request_t, req_type);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_pml_complete,
                          qh_type, mca_pml_base_request_t, req_pml_complete);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_send_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_base_send_request_t";
            goto type_missing;
        }
        i_info->mca_pml_base_send_request_t.type = qh_type;
        i_info->mca_pml_base_send_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_base_send_request_t.offset.req_addr,
                          qh_type, mca_pml_base_send_request_t, req_addr);
        ompi_field_offset(i_info->mca_pml_base_send_request_t.offset.req_bytes_packed,
                          qh_type, mca_pml_base_send_request_t, req_bytes_packed);
        ompi_field_offset(i_info->mca_pml_base_send_request_t.offset.req_send_mode,
                          qh_type, mca_pml_base_send_request_t, req_send_mode);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_recv_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_base_recv_request_t";
            goto type_missing;
        }
        i_info->mca_pml_base_recv_request_t.type = qh_type;
        i_info->mca_pml_base_recv_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_base_recv_request_t.offset.req_bytes_packed,
                          qh_type, mca_pml_base_recv_request_t, req_bytes_packed);
    }
    /*
     * Gather information about the received fragments and theirs headers.
     */
#if 0  /* Disabled until I find a better way */
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_common_hdr_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_ob1_common_hdr_t";
            goto type_missing;
        }
        i_info->mca_pml_ob1_common_hdr_t.type = qh_type;
        i_info->mca_pml_ob1_common_hdr_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_ob1_common_hdr_t.offset.hdr_type,
                          qh_type, mca_pml_ob1_common_hdr_t, hdr_type);
        ompi_field_offset(i_info->mca_pml_ob1_common_hdr_t.offset.hdr_flags,
                          qh_type, mca_pml_ob1_common_hdr_t, hdr_flags);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_match_hdr_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_ob1_match_hdr_t";
            goto type_missing;
        }
        i_info->mca_pml_ob1_match_hdr_t.type = qh_type;
        i_info->mca_pml_ob1_match_hdr_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_common,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_common);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_ctx,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_ctx);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_src,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_src);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_tag,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_tag);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_seq,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_seq);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_recv_frag_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_ob1_recv_frag_t";
            goto type_missing;
        }
        i_info->mca_pml_ob1_recv_frag_t.type = qh_type;
        i_info->mca_pml_ob1_recv_frag_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_ob1_recv_frag_t.offset.hdr,
                          qh_type, mca_pml_ob1_recv_frag_t, hdr);
        ompi_field_offset(i_info->mca_pml_ob1_recv_frag_t.offset.request,
                          qh_type, mca_pml_ob1_recv_frag_t, request);
    }
#endif
    /*
     * And now let's look at the communicator and group structures.
     */
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_pointer_array_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_pointer_array_t";
            goto type_missing;
        }
        i_info->opal_pointer_array_t.type = qh_type;
        i_info->opal_pointer_array_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.lowest_free,
                          qh_type, opal_pointer_array_t, lowest_free);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.number_free,
                          qh_type, opal_pointer_array_t, number_free);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.size,
                          qh_type, opal_pointer_array_t, size);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.addr,
                          qh_type, opal_pointer_array_t, addr);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_communicator_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_communicator_t";
            goto type_missing;
        }
        i_info->ompi_communicator_t.type = qh_type;
        i_info->ompi_communicator_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_name,
                          qh_type, ompi_communicator_t, c_name);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_contextid,
                          qh_type, ompi_communicator_t, c_contextid);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_my_rank,
                          qh_type, ompi_communicator_t, c_my_rank);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_local_group,
                          qh_type, ompi_communicator_t, c_local_group);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_remote_group,
                          qh_type, ompi_communicator_t, c_remote_group);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_flags,
                          qh_type, ompi_communicator_t, c_flags);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_f_to_c_index,
                          qh_type, ompi_communicator_t, c_f_to_c_index);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_topo_comm,
                          qh_type, ompi_communicator_t, c_topo_comm);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_keyhash,
                          qh_type, ompi_communicator_t, c_keyhash);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_topo_base_comm_1_0_0_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_topo_base_comm_1_0_0_t";
            goto type_missing;
        }
        i_info->ompi_mca_topo_base_comm_1_0_0_t.type = qh_type;
        i_info->ompi_mca_topo_base_comm_1_0_0_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_ndims_or_nnodes,
                          qh_type, mca_topo_base_comm_1_0_0_t, mtc_ndims_or_nnodes);
        ompi_field_offset(i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_dims_or_index,
                          qh_type, mca_topo_base_comm_1_0_0_t, mtc_dims_or_index);
        ompi_field_offset(i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_periods_or_edges,
                          qh_type, mca_topo_base_comm_1_0_0_t, mtc_periods_or_edges);
        ompi_field_offset(i_info->ompi_mca_topo_base_comm_1_0_0_t.offset.mtc_reorder,
                          qh_type, mca_topo_base_comm_1_0_0_t, mtc_reorder);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_group_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_group_t";
            goto type_missing;
        }
        i_info->ompi_group_t.type = qh_type;
        i_info->ompi_group_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_proc_count,
                          qh_type, ompi_group_t, grp_proc_count);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_proc_pointers,
                          qh_type, ompi_group_t, grp_proc_pointers);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_my_rank,
                          qh_type, ompi_group_t, grp_my_rank);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_flags,
                          qh_type, ompi_group_t, grp_flags);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_status_public_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_status_public_t";
            goto type_missing;
        }
        i_info->ompi_status_public_t.type = qh_type;
        i_info->ompi_status_public_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_status_public_t.offset.MPI_SOURCE,
                          qh_type, ompi_status_public_t, MPI_SOURCE);
        ompi_field_offset(i_info->ompi_status_public_t.offset.MPI_TAG,
                          qh_type, ompi_status_public_t, MPI_TAG);
        ompi_field_offset(i_info->ompi_status_public_t.offset.MPI_ERROR,
                          qh_type, ompi_status_public_t, MPI_ERROR);
        ompi_field_offset(i_info->ompi_status_public_t.offset._count,
                          qh_type, ompi_status_public_t, _count);
        ompi_field_offset(i_info->ompi_status_public_t.offset._cancelled,
                          qh_type, ompi_status_public_t, _cancelled);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_datatype_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_datatype_t";
            goto type_missing;
        }
        i_info->ompi_datatype_t.type = qh_type;
        i_info->ompi_datatype_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_datatype_t.offset.size,
                          qh_type, ompi_datatype_t, size);
        ompi_field_offset(i_info->ompi_datatype_t.offset.name,
                          qh_type, ompi_datatype_t, name);
    }

    /* All the types are here. Let's succesfully return. */
    *message = NULL;
    return mqs_ok;

 type_missing:
    /*
     * One of the required types is missing in the image. We are
     * unable to extract the information we need from the pointers. We
     * did our best but here we're at our limit. Give up!
     */
    *message = missing_in_action;
    printf( "The following type is missing %s\n", missing_in_action );
    return err_missing_type;
}
Beispiel #3
0
/*
 * Open MPI use a bunch of lists in order to keep track of the
 * internal objects. We have to make sure we're able to find all of
 * them in the image and compute their ofset in order to be able to
 * parse them later.  We need to find the opal_list_item_t, the
 * opal_list_t, the opal_free_list_item_t, and the opal_free_list_t.
 *
 * Once we have these offsets, we should make sure that we have access
 * to all requests lists and types. We're looking here only at the
 * basic type for the requests as they hold all the information we
 * need to export to the debugger.
 */
int ompi_fill_in_type_info(mqs_image *image, char **message)
{
    char* missing_in_action;
    mpi_image_info * i_info = (mpi_image_info *)mqs_get_image_info (image);

    {
        mqs_type* qh_type = mqs_find_type( image, "opal_list_item_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_list_item_t";
            goto type_missing;
        }
        i_info->opal_list_item_t.type = qh_type;
        i_info->opal_list_item_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_list_item_t.offset.opal_list_next,
                          qh_type, opal_list_item_t, opal_list_next);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_list_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_list_t";
            goto type_missing;
        }
        i_info->opal_list_t.type = qh_type;
        i_info->opal_list_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_list_t.offset.opal_list_sentinel,
                          qh_type, opal_list_t, opal_list_sentinel);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_free_list_item_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_free_list_item_t";
            goto type_missing;
        }
        /* This is just an overloaded opal_list_item_t */
        i_info->opal_free_list_item_t.type = qh_type;
        i_info->opal_free_list_item_t.size = mqs_sizeof(qh_type);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_free_list_t", mqs_lang_c );

        if( !qh_type ) {
            missing_in_action = "opal_free_list_t";
            goto type_missing;
        }

        i_info->opal_free_list_t.type = qh_type;
        i_info->opal_free_list_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_mpool,
                          qh_type, opal_free_list_t, fl_mpool);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_allocations,
                          qh_type, opal_free_list_t, fl_allocations);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_frag_class,
                          qh_type, opal_free_list_t, fl_frag_class);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_frag_size,
                          qh_type, opal_free_list_t, fl_frag_size);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_frag_alignment,
                          qh_type, opal_free_list_t, fl_frag_alignment);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_max_to_alloc,
                          qh_type, opal_free_list_t, fl_max_to_alloc);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_num_per_alloc,
                          qh_type, opal_free_list_t, fl_num_per_alloc);
        ompi_field_offset(i_info->opal_free_list_t.offset.fl_num_allocated,
                          qh_type, opal_free_list_t, fl_num_allocated);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_hash_table_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_hash_table_t";
            goto type_missing;
        }
        i_info->opal_hash_table_t.type = qh_type;
        i_info->opal_hash_table_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_hash_table_t.offset.ht_table,
                          qh_type, opal_hash_table_t, ht_table);
        ompi_field_offset(i_info->opal_hash_table_t.offset.ht_size,
                          qh_type, opal_hash_table_t, ht_size);
    }
    /*
     * Now let's look for all types required for reading the requests.
     */
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_request_t";
            goto type_missing;
        }
        i_info->ompi_request_t.type = qh_type;
        i_info->ompi_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_request_t.offset.req_type,
                          qh_type, ompi_request_t, req_type);
        ompi_field_offset(i_info->ompi_request_t.offset.req_status,
                          qh_type, ompi_request_t, req_status);
        ompi_field_offset(i_info->ompi_request_t.offset.req_complete,
                          qh_type, ompi_request_t, req_complete);
        ompi_field_offset(i_info->ompi_request_t.offset.req_state,
                          qh_type, ompi_request_t, req_state);
        ompi_field_offset(i_info->ompi_request_t.offset.req_f_to_c_index,
                          qh_type, ompi_request_t, req_f_to_c_index);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_base_request_t";
            goto type_missing;
        }
        i_info->mca_pml_base_request_t.type = qh_type;
        i_info->mca_pml_base_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_addr,
                          qh_type, mca_pml_base_request_t, req_addr);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_count,
                          qh_type, mca_pml_base_request_t, req_count);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_peer,
                          qh_type, mca_pml_base_request_t, req_peer);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_tag,
                          qh_type, mca_pml_base_request_t, req_tag);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_comm,
                          qh_type, mca_pml_base_request_t, req_comm);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_datatype,
                          qh_type, mca_pml_base_request_t, req_datatype);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_proc,
                          qh_type, mca_pml_base_request_t, req_proc);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_sequence,
                          qh_type, mca_pml_base_request_t, req_sequence);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_type,
                          qh_type, mca_pml_base_request_t, req_type);
        ompi_field_offset(i_info->mca_pml_base_request_t.offset.req_pml_complete,
                          qh_type, mca_pml_base_request_t, req_pml_complete);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_send_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_base_send_request_t";
            goto type_missing;
        }
        i_info->mca_pml_base_send_request_t.type = qh_type;
        i_info->mca_pml_base_send_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_base_send_request_t.offset.req_addr,
                          qh_type, mca_pml_base_send_request_t, req_addr);
        ompi_field_offset(i_info->mca_pml_base_send_request_t.offset.req_bytes_packed,
                          qh_type, mca_pml_base_send_request_t, req_bytes_packed);
        ompi_field_offset(i_info->mca_pml_base_send_request_t.offset.req_send_mode,
                          qh_type, mca_pml_base_send_request_t, req_send_mode);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_base_recv_request_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_base_recv_request_t";
            goto type_missing;
        }
        i_info->mca_pml_base_recv_request_t.type = qh_type;
        i_info->mca_pml_base_recv_request_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_base_recv_request_t.offset.req_bytes_packed,
                          qh_type, mca_pml_base_recv_request_t, req_bytes_packed);
    }
    /*
     * Gather information about the received fragments and theirs headers.
     */
#if 0  /* Disabled until I find a better way */
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_common_hdr_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_ob1_common_hdr_t";
            goto type_missing;
        }
        i_info->mca_pml_ob1_common_hdr_t.type = qh_type;
        i_info->mca_pml_ob1_common_hdr_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_ob1_common_hdr_t.offset.hdr_type,
                          qh_type, mca_pml_ob1_common_hdr_t, hdr_type);
        ompi_field_offset(i_info->mca_pml_ob1_common_hdr_t.offset.hdr_flags,
                          qh_type, mca_pml_ob1_common_hdr_t, hdr_flags);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_match_hdr_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_ob1_match_hdr_t";
            goto type_missing;
        }
        i_info->mca_pml_ob1_match_hdr_t.type = qh_type;
        i_info->mca_pml_ob1_match_hdr_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_common,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_common);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_ctx,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_ctx);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_src,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_src);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_tag,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_tag);
        ompi_field_offset(i_info->mca_pml_ob1_match_hdr_t.offset.hdr_seq,
                          qh_type, mca_pml_ob1_match_hdr_t, hdr_seq);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "mca_pml_ob1_recv_frag_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "mca_pml_ob1_recv_frag_t";
            goto type_missing;
        }
        i_info->mca_pml_ob1_recv_frag_t.type = qh_type;
        i_info->mca_pml_ob1_recv_frag_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->mca_pml_ob1_recv_frag_t.offset.hdr,
                          qh_type, mca_pml_ob1_recv_frag_t, hdr);
        ompi_field_offset(i_info->mca_pml_ob1_recv_frag_t.offset.request,
                          qh_type, mca_pml_ob1_recv_frag_t, request);
    }
#endif
    /*
     * And now let's look at the communicator and group structures.
     */
    {
        mqs_type* qh_type = mqs_find_type( image, "opal_pointer_array_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "opal_pointer_array_t";
            goto type_missing;
        }
        i_info->opal_pointer_array_t.type = qh_type;
        i_info->opal_pointer_array_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.lowest_free,
                          qh_type, opal_pointer_array_t, lowest_free);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.number_free,
                          qh_type, opal_pointer_array_t, number_free);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.size,
                          qh_type, opal_pointer_array_t, size);
        ompi_field_offset(i_info->opal_pointer_array_t.offset.addr,
                          qh_type, opal_pointer_array_t, addr);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_communicator_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_communicator_t";
            goto type_missing;
        }
        i_info->ompi_communicator_t.type = qh_type;
        i_info->ompi_communicator_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_name,
                          qh_type, ompi_communicator_t, c_name);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_contextid,
                          qh_type, ompi_communicator_t, c_contextid);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_my_rank,
                          qh_type, ompi_communicator_t, c_my_rank);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_local_group,
                          qh_type, ompi_communicator_t, c_local_group);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_remote_group,
                          qh_type, ompi_communicator_t, c_remote_group);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_flags,
                          qh_type, ompi_communicator_t, c_flags);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_f_to_c_index,
                          qh_type, ompi_communicator_t, c_f_to_c_index);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_topo,
                          qh_type, ompi_communicator_t, c_topo);
        ompi_field_offset(i_info->ompi_communicator_t.offset.c_keyhash,
                          qh_type, ompi_communicator_t, c_keyhash);
    }
    {
        mqs_type* qh_type, *cart_type, *graph_type, *dist_graph_type;
        int offset = 0;

        missing_in_action = "mca_topo_base_module_t";
        qh_type = mqs_find_type(image, missing_in_action, mqs_lang_c);
        if( !qh_type ) {
            goto type_missing;
        }
        i_info->mca_topo_base_module_t.type = qh_type;
        i_info->mca_topo_base_module_t.size = mqs_sizeof(qh_type);

        /* The topo module contains multiple unions.  These fields are
           outside those unions. */
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc,
                          qh_type, mca_topo_base_module_t, mtc);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.reorder,
                          qh_type, mca_topo_base_module_t, reorder);

        /* By definition, the base offsets are 0 in the union.
	   Above we've got the base union offset, so now look up the
           individual fields in the cart, graph and dist_graph structs and
	   add them to the base union offset.  Then we have the offset of
           that field from the mca_topo_base_module_2_1_0_t type. */

        /* Cart type */
        missing_in_action = "mca_topo_base_comm_cart_2_2_0_t";
        cart_type = mqs_find_type(image, missing_in_action, mqs_lang_c);
        if (!cart_type) {
            goto type_missing;
        }
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_cart.ndims,
                          cart_type, mca_topo_base_comm_cart_2_2_0_t,
                          ndims);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_cart.dims,
                          cart_type, mca_topo_base_comm_cart_2_2_0_t,
                          dims);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_cart.periods,
                          cart_type, mca_topo_base_comm_cart_2_2_0_t,
                          periods);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_cart.coords,
                          cart_type, mca_topo_base_comm_cart_2_2_0_t,
                          coords);
        i_info->mca_topo_base_module_t.offset.mtc_cart.ndims   += offset;
        i_info->mca_topo_base_module_t.offset.mtc_cart.dims    += offset;
        i_info->mca_topo_base_module_t.offset.mtc_cart.periods += offset;
        i_info->mca_topo_base_module_t.offset.mtc_cart.coords  += offset;

        /* Graph type */
        missing_in_action = "mca_topo_base_comm_graph_2_2_0_t";
        graph_type = mqs_find_type(image, missing_in_action, mqs_lang_c);
        if (!graph_type) {
            goto type_missing;
        }
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_graph.nnodes,
                          graph_type, mca_topo_base_comm_graph_2_2_0_t,
                          nnodes);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_graph.index,
                          graph_type, mca_topo_base_comm_graph_2_2_0_t,
                          index);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_graph.edges,
                          graph_type, mca_topo_base_comm_graph_2_2_0_t,
                          edges);
        i_info->mca_topo_base_module_t.offset.mtc_graph.nnodes += offset;
        i_info->mca_topo_base_module_t.offset.mtc_graph.index  += offset;
        i_info->mca_topo_base_module_t.offset.mtc_graph.edges  += offset;

        /* Distributed Graph type */
        missing_in_action = "mca_topo_base_comm_dist_graph_2_2_0_t";
        dist_graph_type = mqs_find_type(image, missing_in_action, mqs_lang_c);
        if (!dist_graph_type) {
            goto type_missing;
        }
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.in,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          in);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.inw,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          inw);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.out,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          out);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.outw,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          outw);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.indegree,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          indegree);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.outdegree,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          outdegree);
        ompi_field_offset(i_info->mca_topo_base_module_t.offset.mtc_dist_graph.weighted,
                          dist_graph_type, mca_topo_base_comm_dist_graph_2_2_0_t,
                          weighted);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_group_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_group_t";
            goto type_missing;
        }
        i_info->ompi_group_t.type = qh_type;
        i_info->ompi_group_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_proc_count,
                          qh_type, ompi_group_t, grp_proc_count);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_proc_pointers,
                          qh_type, ompi_group_t, grp_proc_pointers);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_my_rank,
                          qh_type, ompi_group_t, grp_my_rank);
        ompi_field_offset(i_info->ompi_group_t.offset.grp_flags,
                          qh_type, ompi_group_t, grp_flags);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_status_public_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_status_public_t";
            goto type_missing;
        }
        i_info->ompi_status_public_t.type = qh_type;
        i_info->ompi_status_public_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_status_public_t.offset.MPI_SOURCE,
                          qh_type, ompi_status_public_t, MPI_SOURCE);
        ompi_field_offset(i_info->ompi_status_public_t.offset.MPI_TAG,
                          qh_type, ompi_status_public_t, MPI_TAG);
        ompi_field_offset(i_info->ompi_status_public_t.offset.MPI_ERROR,
                          qh_type, ompi_status_public_t, MPI_ERROR);
        ompi_field_offset(i_info->ompi_status_public_t.offset._ucount,
                          qh_type, ompi_status_public_t, _ucount);
        ompi_field_offset(i_info->ompi_status_public_t.offset._cancelled,
                          qh_type, ompi_status_public_t, _cancelled);
    }
    {
        mqs_type* qh_type = mqs_find_type( image, "ompi_datatype_t", mqs_lang_c );
        if( !qh_type ) {
            missing_in_action = "ompi_datatype_t";
            goto type_missing;
        }
        i_info->ompi_datatype_t.type = qh_type;
        i_info->ompi_datatype_t.size = mqs_sizeof(qh_type);
        ompi_field_offset(i_info->ompi_datatype_t.offset.name,
                          qh_type, ompi_datatype_t, name);

        /* get ompi_datatype_t super.size which requires the offset
         * of super and then the offset of size in opal_datatype_t.
         */
        {
            int super_offset = 0;

            ompi_field_offset(super_offset,
                              qh_type, ompi_datatype_t, super);

            qh_type = mqs_find_type( image, "opal_datatype_t", mqs_lang_c );
            if( !qh_type ) {
                missing_in_action = "opal_datatype_t";
                goto type_missing;
            }
            ompi_field_offset(i_info->ompi_datatype_t.offset.size,
                              qh_type, opal_datatype_t, size);
            i_info->ompi_datatype_t.offset.size += super_offset;
        }
    }

    /* All the types are here. Let's succesfully return. */
    *message = NULL;
    return mqs_ok;

 type_missing:
    /*
     * One of the required types is missing in the image. We are
     * unable to extract the information we need from the pointers. We
     * did our best but here we're at our limit. Give up!
     */
    *message = missing_in_action;
    fprintf(stderr, "WARNING: Open MPI is unable to find debugging information about the \"%s\" type.  This can happen if Open MPI was built without debugging information, or was stripped after building.\n",
           missing_in_action);
    return err_missing_type;
}