1 /*
2  * Copyright © 2009 CNRS
3  * Copyright © 2009-2019 Inria.  All rights reserved.
4  * Copyright © 2009-2012 Université Bordeaux
5  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
6  * See COPYING in top-level directory.
7  */
8 
9 #include <private/autogen/config.h>
10 #include <hwloc.h>
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <assert.h>
17 
18 #include "misc.h"
19 #include "hwloc-calc.h"
20 
21 static int pid_number = -1;
22 static hwloc_pid_t pid;
23 static int verbose_mode = 0;
24 static int logical = 1;
25 static int show_ancestors = 0;
26 static hwloc_obj_type_t show_ancestor_type = (hwloc_obj_type_t) -1;
27 static int show_ancestor_attrdepth = -1;
28 static hwloc_obj_cache_type_t show_ancestor_attrcachetype = (hwloc_obj_cache_type_t) -1;
29 static int show_children = 0;
30 static int show_descendants_depth = HWLOC_TYPE_DEPTH_UNKNOWN;
31 static int show_index_prefix = 0;
32 static unsigned current_obj;
33 
usage(const char * name,FILE * where)34 void usage(const char *name, FILE *where)
35 {
36   fprintf (where, "Usage: %s [ options ] [ locations ]\n", name);
37   fprintf (where, "\nOutput options:\n");
38   fprintf (where, "  --objects             Report information about specific objects\n");
39   fprintf (where, "  --topology            Report information the topology\n");
40   fprintf (where, "  --support             Report information about supported features\n");
41   fprintf (where, "  -v --verbose          Include additional details\n");
42   fprintf (where, "  -s --silent           Reduce the amount of details to show\n");
43   fprintf (where, "  --ancestors           Display the chain of ancestor objects up to the root\n");
44   fprintf (where, "  --ancestor <type>     Only display the ancestor of the given type\n");
45   fprintf (where, "  --children            Display all children\n");
46   fprintf (where, "  --descendants <type>  Only display descendants of the given type\n");
47   fprintf (where, "  -n                    Prefix each line with the index of the considered object\n");
48   fprintf (where, "Object filtering options:\n");
49   fprintf (where, "  --restrict <cpuset>   Restrict the topology to processors listed in <cpuset>\n");
50   fprintf (where, "  --restrict binding    Restrict the topology to the current process binding\n");
51   fprintf (where, "  --no-icaches          Do not show instruction caches\n");
52   fprintf (where, "  --no-io               Do not show any I/O device or bridge\n");
53   fprintf (where, "  --no-bridges          Do not any I/O bridge except hostbridges\n");
54   fprintf (where, "  --whole-io            Show all I/O devices and bridges\n");
55   fprintf (where, "Input options:\n");
56   hwloc_utils_input_format_usage(where, 6);
57   fprintf (where, "  --thissystem          Assume that the input topology provides the topology\n"
58 		  "                        for the system on which we are running\n");
59   fprintf (where, "  --pid <pid>           Detect topology as seen by process <pid>\n");
60   fprintf (where, "  --whole-system        Do not consider administration limitations\n");
61   fprintf (where, "  -l --logical          Use logical object indexes for input (default)\n");
62   fprintf (where, "  -p --physical         Use physical object indexes for input\n");
63   fprintf (where, "Miscellaneous options:\n");
64   fprintf (where, "  --version             Report version and exit\n");
65 }
66 
67 static void
hwloc_info_show_obj(hwloc_obj_t obj,const char * type,const char * prefix,int verbose)68 hwloc_info_show_obj(hwloc_obj_t obj, const char *type, const char *prefix, int verbose)
69 {
70   char s[128];
71   unsigned i;
72   if (verbose < 0)
73     return;
74   printf("%s type = %s\n", prefix, hwloc_obj_type_string(obj->type));
75   printf("%s full type = %s\n", prefix, type);
76   printf("%s logical index = %u\n", prefix, obj->logical_index);
77   if (obj->os_index != (unsigned) -1)
78     printf("%s os index = %u\n", prefix, obj->os_index);
79   if (obj->name)
80     printf("%s name = %s\n", prefix, obj->name);
81   if (obj->depth != (unsigned) -1)
82     printf("%s depth = %d\n", prefix, (int) obj->depth); /* special levels have negative values */
83   printf("%s sibling rank = %u\n", prefix, obj->sibling_rank);
84   printf("%s children = %u\n", prefix, obj->arity);
85   if (obj->memory.local_memory)
86     printf("%s local memory = %llu\n", prefix, (unsigned long long) obj->memory.local_memory);
87   if (obj->memory.total_memory)
88     printf("%s total memory = %llu\n", prefix, (unsigned long long) obj->memory.total_memory);
89 
90   if (obj->cpuset) {
91     hwloc_bitmap_snprintf(s, sizeof(s), obj->cpuset);
92     printf("%s cpuset = %s\n", prefix, s);
93   }
94   if (obj->complete_cpuset) {
95     hwloc_bitmap_snprintf(s, sizeof(s), obj->complete_cpuset);
96     printf("%s complete cpuset = %s\n", prefix, s);
97   }
98   if (obj->online_cpuset) {
99     hwloc_bitmap_snprintf(s, sizeof(s), obj->online_cpuset);
100     printf("%s online cpuset = %s\n", prefix, s);
101   }
102   if (obj->allowed_cpuset) {
103     hwloc_bitmap_snprintf(s, sizeof(s), obj->allowed_cpuset);
104     printf("%s allowed cpuset = %s\n", prefix, s);
105   }
106 
107   if (obj->nodeset) {
108     hwloc_bitmap_snprintf(s, sizeof(s), obj->nodeset);
109     printf("%s nodeset = %s\n", prefix, s);
110   }
111   if (obj->complete_nodeset) {
112     hwloc_bitmap_snprintf(s, sizeof(s), obj->complete_nodeset);
113     printf("%s complete nodeset = %s\n", prefix, s);
114   }
115   if (obj->allowed_nodeset) {
116     hwloc_bitmap_snprintf(s, sizeof(s), obj->allowed_nodeset);
117     printf("%s allowed nodeset = %s\n", prefix, s);
118   }
119 
120   switch (obj->type) {
121   case HWLOC_OBJ_CACHE:
122     printf("%s attr cache depth = %u\n", prefix, obj->attr->cache.depth);
123     switch (obj->attr->cache.type) {
124     case HWLOC_OBJ_CACHE_UNIFIED: printf("%s attr cache type = Unified\n", prefix); break;
125     case HWLOC_OBJ_CACHE_DATA: printf("%s attr cache type = Data\n", prefix); break;
126     case HWLOC_OBJ_CACHE_INSTRUCTION: printf("%s attr cache type = Instruction\n", prefix); break;
127     }
128     printf("%s attr cache size = %llu\n", prefix, (unsigned long long) obj->attr->cache.size);
129     printf("%s attr cache line size = %u\n", prefix, obj->attr->cache.linesize);
130     if (obj->attr->cache.associativity == -1)
131       printf("%s attr cache ways = Fully-associative\n", prefix);
132     else if (obj->attr->cache.associativity != 0)
133       printf("%s attr cache ways = %d\n", prefix, obj->attr->cache.associativity);
134     break;
135   case HWLOC_OBJ_GROUP:
136     printf("%s attr group depth = %u\n", prefix, obj->attr->group.depth);
137     break;
138   case HWLOC_OBJ_BRIDGE:
139     switch (obj->attr->bridge.upstream_type) {
140     case HWLOC_OBJ_BRIDGE_HOST:
141       printf("%s attr bridge upstream type = Host\n", prefix);
142       break;
143     case HWLOC_OBJ_BRIDGE_PCI:
144       printf("%s attr bridge upstream type = PCI\n", prefix);
145       printf("%s attr PCI bus id = %04x:%02x:%02x.%01x\n",
146 	     prefix, obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func);
147       printf("%s attr PCI class = %04x\n",
148 	     prefix, obj->attr->pcidev.class_id);
149       printf("%s attr PCI id = %04x:%04x\n",
150 	     prefix, obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id);
151       if (obj->attr->pcidev.linkspeed)
152 	printf("%s attr PCI linkspeed = %f GB/s\n", prefix, obj->attr->pcidev.linkspeed);
153       break;
154     }
155     switch (obj->attr->bridge.downstream_type) {
156     case HWLOC_OBJ_BRIDGE_HOST:
157       assert(0);
158     case HWLOC_OBJ_BRIDGE_PCI:
159       printf("%s attr bridge downstream type = PCI\n", prefix);
160       printf("%s attr PCI secondary bus = %02x\n",
161 	     prefix, obj->attr->bridge.downstream.pci.secondary_bus);
162       printf("%s attr PCI subordinate bus = %02x\n",
163 	     prefix, obj->attr->bridge.downstream.pci.subordinate_bus);
164       break;
165     }
166     break;
167   case HWLOC_OBJ_PCI_DEVICE:
168     printf("%s attr PCI bus id = %04x:%02x:%02x.%01x\n",
169 	   prefix, obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func);
170     printf("%s attr PCI class = %04x\n",
171 	   prefix, obj->attr->pcidev.class_id);
172     printf("%s attr PCI id = %04x:%04x\n",
173 	   prefix, obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id);
174     if (obj->attr->pcidev.linkspeed)
175       printf("%s attr PCI linkspeed = %f GB/s\n", prefix, obj->attr->pcidev.linkspeed);
176     break;
177   case HWLOC_OBJ_OS_DEVICE:
178     printf("%s attr osdev type = %s\n", prefix, type);
179     break;
180   default:
181     /* nothing to show */
182     break;
183   }
184 
185   printf("%s symmetric subtree = %d\n", prefix, obj->symmetric_subtree);
186 
187   for(i=0; i<obj->infos_count; i++) {
188     printf("%s info %s = %s\n", prefix, obj->infos[i].name, obj->infos[i].value);
189   }
190 }
191 
192 static void
hwloc_calc_process_location_info_cb(struct hwloc_calc_location_context_s * lcontext,void * _data __hwloc_attribute_unused,hwloc_obj_t obj)193 hwloc_calc_process_location_info_cb(struct hwloc_calc_location_context_s *lcontext,
194 				    void *_data __hwloc_attribute_unused,
195 				    hwloc_obj_t obj)
196 {
197   hwloc_topology_t topology = lcontext->topology;
198   int verbose = lcontext->verbose;
199   char prefix[32];
200   char objs[128];
201 
202   prefix[0] = '\0';
203   if (show_index_prefix)
204     snprintf(prefix, sizeof(prefix), "%u: ", current_obj);
205 
206   hwloc_obj_type_snprintf(objs, sizeof(objs), obj, 1);
207 
208   if (show_ancestors) {
209     char parents[128];
210     unsigned level = 0;
211     hwloc_obj_t parent = obj;
212     while (parent) {
213       if (show_index_prefix)
214 	snprintf(prefix, sizeof(prefix), "%u.%u: ", current_obj, level);
215       hwloc_obj_type_snprintf(parents, sizeof(parents), parent, 1);
216       if (verbose < 0)
217 	printf("%s%s:%u\n", prefix, parents, parent->logical_index);
218       else if (level)
219 	printf("%s%s L#%u = parent #%u of %s L#%u\n",
220 	       prefix, parents, parent->logical_index, level, objs, obj->logical_index);
221       else
222 	printf("%s%s L#%u\n", prefix, parents, parent->logical_index);
223       hwloc_info_show_obj(parent, parents, prefix, verbose);
224       parent = parent->parent;
225       level++;
226     }
227   } else if (show_ancestor_type != (hwloc_obj_type_t) -1) {
228     char parents[128];
229     hwloc_obj_t parent = obj;
230     while (parent) {
231       if (parent->type == show_ancestor_type) {
232 	if (parent->type == HWLOC_OBJ_GROUP
233 	    && show_ancestor_attrdepth != -1
234 	    && show_ancestor_attrdepth != (int) parent->attr->group.depth)
235 	  goto next;
236 	if (parent->type == HWLOC_OBJ_CACHE
237 	    && show_ancestor_attrdepth != -1
238 	    && show_ancestor_attrdepth != (int) parent->attr->cache.depth)
239 	  goto next;
240 	if (parent->type == HWLOC_OBJ_CACHE
241 	    && show_ancestor_attrcachetype != (hwloc_obj_cache_type_t) -1
242 	    && parent->attr->cache.type != HWLOC_OBJ_CACHE_UNIFIED
243 	    && show_ancestor_attrcachetype != parent->attr->cache.type)
244 	  goto next;
245 	hwloc_obj_type_snprintf(parents, sizeof(parents), parent, 1);
246 	if (verbose < 0)
247 	  printf("%s%s:%u\n", prefix, parents, parent->logical_index);
248 	else
249 	  printf("%s%s L#%u = parent of %s L#%u\n",
250 		 prefix, parents, parent->logical_index, objs, obj->logical_index);
251 	hwloc_info_show_obj(parent, parents, prefix, verbose);
252       }
253 next:
254       parent = parent->parent;
255     }
256   } else if (show_children) {
257     unsigned i = 0;
258     hwloc_obj_t child = NULL;
259     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
260       char childs[128];
261       if (show_index_prefix)
262 	snprintf(prefix, sizeof(prefix), "%u.%u: ", current_obj, i);
263       hwloc_obj_type_snprintf(childs, sizeof(childs), child, 1);
264       if (verbose < 0)
265 	printf("%s%s:%u\n", prefix, childs, child->logical_index);
266       else
267 	printf("%s%s L#%u = child #%u of %s L#%u\n",
268 	       prefix, childs, child->logical_index, i, objs, obj->logical_index);
269       hwloc_info_show_obj(child, childs, prefix, verbose);
270       i++;
271     }
272   } else if (show_descendants_depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
273     if (show_descendants_depth >= 0) {
274       /* normal level */
275       unsigned i = 0;
276       unsigned n = hwloc_calc_get_nbobjs_inside_sets_by_depth(lcontext, obj->cpuset, obj->nodeset, show_descendants_depth);
277       for(i=0; i<n; i++) {
278 	hwloc_obj_t child = hwloc_calc_get_obj_inside_sets_by_depth(lcontext, obj->cpuset, obj->nodeset, show_descendants_depth, i);
279 	char childs[128];
280 	if (show_index_prefix)
281 	  snprintf(prefix, sizeof(prefix), "%u.%u: ", current_obj, i);
282 	hwloc_obj_type_snprintf(childs, sizeof(childs), child, 1);
283 	if (verbose < 0)
284 	  printf("%s%s:%u\n", prefix, childs, child->logical_index);
285 	else
286 	  printf("%s%s L#%u = descendant #%u of %s L#%u\n",
287 		 prefix, childs, child->logical_index, i, objs, obj->logical_index);
288 	hwloc_info_show_obj(child, childs, prefix, verbose);
289       }
290     } else {
291       /* custom level */
292       unsigned i = 0;
293       hwloc_obj_t child = NULL;
294       while ((child = hwloc_get_next_obj_by_depth(topology, show_descendants_depth, child)) != NULL) {
295 	char childs[128];
296 	hwloc_obj_t parent = child->parent;
297 	if (obj->cpuset) {
298 	  while (parent && !parent->cpuset)
299 	    parent = parent->parent;
300 	  if (!parent)
301 	    continue;
302 	  if (!hwloc_bitmap_isincluded(parent->cpuset, obj->cpuset)
303 	      || !hwloc_bitmap_isincluded(parent->nodeset, obj->nodeset))
304 	    continue;
305 	} else {
306 	  while (parent && parent != obj)
307 	    parent = parent->parent;
308 	  if (!parent)
309 	    continue;
310 	}
311 	if (show_index_prefix)
312 	  snprintf(prefix, sizeof(prefix), "%u.%u: ", current_obj, i);
313 	hwloc_obj_type_snprintf(childs, sizeof(childs), child, 1);
314 	if (verbose < 0)
315 	  printf("%s%s:%u\n", prefix, childs, child->logical_index);
316 	else
317 	  printf("%s%s L#%u = descendant #%u of %s L#%u\n",
318 		 prefix, childs, child->logical_index, i, objs, obj->logical_index);
319 	hwloc_info_show_obj(child, childs, prefix, verbose);
320 	i++;
321       }
322     }
323   } else {
324     if (verbose < 0)
325       printf("%s%s:%u\n", prefix, objs, obj->logical_index);
326     else
327       printf("%s%s L#%u\n", prefix, objs, obj->logical_index);
328     hwloc_info_show_obj(obj, objs, prefix, verbose);
329   }
330 
331   current_obj++;
332 }
333 
334 int
main(int argc,char * argv[])335 main (int argc, char *argv[])
336 {
337   int err;
338   hwloc_topology_t topology;
339   unsigned topodepth;
340   unsigned long flags = HWLOC_TOPOLOGY_FLAG_IO_DEVICES | HWLOC_TOPOLOGY_FLAG_IO_BRIDGES | HWLOC_TOPOLOGY_FLAG_ICACHES;
341   char * callname;
342   char * input = NULL;
343   enum hwloc_utils_input_format input_format = HWLOC_UTILS_INPUT_DEFAULT;
344   hwloc_obj_type_t show_descendants_type = (hwloc_obj_type_t) -1;
345   int show_descendants_attrdepth = -1;
346   hwloc_obj_cache_type_t show_descendants_attrcachetype = (hwloc_obj_cache_type_t) -1;
347   char *restrictstring = NULL;
348   size_t typelen;
349   int opt;
350   enum hwloc_info_mode { HWLOC_INFO_MODE_UNKNOWN, HWLOC_INFO_MODE_TOPOLOGY, HWLOC_INFO_MODE_OBJECTS, HWLOC_INFO_MODE_SUPPORT } mode = HWLOC_INFO_MODE_UNKNOWN;
351 
352   /* enable verbose backends */
353   putenv((char *) "HWLOC_XML_VERBOSE=1");
354   putenv((char *) "HWLOC_SYNTHETIC_VERBOSE=1");
355 
356   callname = strrchr(argv[0], '/');
357   if (!callname)
358     callname = argv[0];
359   else
360     callname++;
361   /* skip argv[0], handle options */
362   argc--;
363   argv++;
364 
365   err = hwloc_topology_init (&topology);
366   if (err)
367     return EXIT_FAILURE;
368 
369   hwloc_topology_set_flags(topology, flags);
370 
371   while (argc >= 1) {
372     opt = 0;
373     if (*argv[0] == '-') {
374       if (!strcmp (argv[0], "--objects"))
375 	mode = HWLOC_INFO_MODE_OBJECTS;
376       else if (!strcmp (argv[0], "--topology"))
377 	mode = HWLOC_INFO_MODE_TOPOLOGY;
378       else if (!strcmp (argv[0], "--support"))
379 	mode = HWLOC_INFO_MODE_SUPPORT;
380       else if (!strcmp (argv[0], "-v") || !strcmp (argv[0], "--verbose"))
381         verbose_mode++;
382       else if (!strcmp (argv[0], "-s") || !strcmp (argv[0], "--silent"))
383         verbose_mode--;
384       else if (!strcmp (argv[0], "-h") || !strcmp (argv[0], "--help")) {
385 	usage(callname, stdout);
386         exit(EXIT_SUCCESS);
387       }
388       else if (!strcmp (argv[0], "-n"))
389 	show_index_prefix = 1;
390       else if (!strcmp (argv[0], "--ancestors"))
391 	show_ancestors = 1;
392       else if (!strcmp (argv[0], "--ancestor")) {
393 	if (argc < 2) {
394 	  usage (callname, stderr);
395 	  exit(EXIT_FAILURE);
396 	}
397 	err = hwloc_obj_type_sscanf(argv[1], &show_ancestor_type, &show_ancestor_attrdepth, &show_ancestor_attrcachetype, sizeof(show_ancestor_attrcachetype));
398         if (err < 0) {
399           fprintf(stderr, "unrecognized --ancestor type %s\n", argv[1]);
400           usage(callname, stderr);
401           return EXIT_FAILURE;
402         }
403 	opt = 1;
404       }
405       else if (!strcmp (argv[0], "--children"))
406 	show_children = 1;
407       else if (!strcmp (argv[0], "--descendants")) {
408 	if (argc < 2) {
409 	  usage (callname, stderr);
410 	  exit(EXIT_FAILURE);
411 	}
412 	err = hwloc_obj_type_sscanf(argv[1], &show_descendants_type, &show_descendants_attrdepth, &show_descendants_attrcachetype, sizeof(show_descendants_attrcachetype));
413         if (err < 0) {
414           fprintf(stderr, "unrecognized --descendants type %s\n", argv[1]);
415           usage(callname, stderr);
416           return EXIT_FAILURE;
417         }
418 	opt = 1;
419       }
420       else if (!strcmp (argv[0], "--no-icaches"))
421 	flags &= ~HWLOC_TOPOLOGY_FLAG_ICACHES;
422       else if (!strcmp (argv[0], "--whole-system"))
423 	flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM;
424       else if (!strcmp (argv[0], "--no-io"))
425 	flags &= ~(HWLOC_TOPOLOGY_FLAG_IO_DEVICES | HWLOC_TOPOLOGY_FLAG_IO_BRIDGES);
426       else if (!strcmp (argv[0], "--no-bridges"))
427 	flags &= ~(HWLOC_TOPOLOGY_FLAG_IO_BRIDGES);
428       else if (!strcmp (argv[0], "--whole-io"))
429 	flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_IO;
430       else if (!strcmp (argv[0], "--thissystem"))
431 	flags |= HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM;
432       else if (!strcmp (argv[0], "--restrict")) {
433 	if (argc < 2) {
434 	  usage (callname, stderr);
435 	  exit(EXIT_FAILURE);
436 	}
437 	restrictstring = strdup(argv[1]);
438 	opt = 1;
439       }
440 
441       else if (hwloc_utils_lookup_input_option(argv, argc, &opt,
442 					       &input, &input_format,
443 					       callname)) {
444 	/* we'll enable later */
445       }
446       else if (!strcmp (argv[0], "--pid")) {
447 	if (argc < 2) {
448 	  usage (callname, stderr);
449 	  exit(EXIT_FAILURE);
450 	}
451 	pid_number = atoi(argv[1]); opt = 1;
452       }
453       else if (!strcmp(argv[0], "-l") || !strcmp(argv[0], "--logical"))
454 	logical = 1;
455       else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--physical"))
456 	logical = 0;
457       else if (!strcmp (argv[0], "--version")) {
458         printf("%s %s\n", callname, HWLOC_VERSION);
459         exit(EXIT_SUCCESS);
460       }
461       else {
462 	fprintf (stderr, "Unrecognized option: %s\n", argv[0]);
463 	usage(callname, stderr);
464 	return EXIT_FAILURE;
465       }
466       argc -= opt+1;
467       argv += opt+1;
468     } else {
469       /* not an option */
470       break;
471     }
472   }
473 
474   hwloc_topology_set_flags(topology, flags);
475 
476   if (input) {
477     err = hwloc_utils_enable_input_format(topology, input, &input_format, verbose_mode, callname);
478     if (err)
479       return err;
480   }
481 
482   if (pid_number > 0) {
483     if (hwloc_pid_from_number(&pid, pid_number, 0, 1 /* verbose */) < 0
484 	|| hwloc_topology_set_pid(topology, pid)) {
485       perror("Setting target pid");
486       return EXIT_FAILURE;
487     }
488   }
489 
490   err = hwloc_topology_load (topology);
491   if (err) {
492     perror("hwloc_topology_load");
493     return EXIT_FAILURE;
494   }
495 
496   topodepth = hwloc_topology_get_depth(topology);
497 
498   if (show_descendants_type != (hwloc_obj_type_t) -1) {
499     show_descendants_depth = hwloc_get_type_depth(topology, show_descendants_type);
500     if (show_descendants_depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
501       fprintf(stderr, "unavailable --descendants type %s\n", hwloc_obj_type_string(show_descendants_type));
502       return EXIT_FAILURE;
503     }
504     if (show_descendants_depth == HWLOC_TYPE_DEPTH_MULTIPLE) {
505       if (show_descendants_type == HWLOC_OBJ_CACHE)
506 	show_descendants_depth = hwloc_get_cache_type_depth(topology, show_descendants_attrdepth, show_descendants_attrcachetype);
507       else if (show_descendants_type == HWLOC_OBJ_GROUP) {
508 	unsigned i;
509 	for(i=0; i<hwloc_topology_get_depth(topology); i++) {
510 	  hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, i, 0);
511 	  if (obj->type == HWLOC_OBJ_GROUP && obj->attr->group.depth == (unsigned) show_descendants_attrdepth) {
512 	    show_descendants_depth = i;
513 	    break;
514 	  }
515         }
516       }
517     }
518     if (show_descendants_depth == HWLOC_TYPE_DEPTH_MULTIPLE) {
519       fprintf(stderr, "multiple --descendants type %s\n", hwloc_obj_type_string(show_descendants_type));
520       return EXIT_FAILURE;
521     }
522   }
523 
524   if (restrictstring) {
525     hwloc_bitmap_t restrictset = hwloc_bitmap_alloc();
526     if (!strcmp (restrictstring, "binding")) {
527       if (pid_number > 0)
528 	hwloc_get_proc_cpubind(topology, pid, restrictset, HWLOC_CPUBIND_PROCESS);
529       else
530 	hwloc_get_cpubind(topology, restrictset, HWLOC_CPUBIND_PROCESS);
531     } else {
532       hwloc_bitmap_sscanf(restrictset, restrictstring);
533     }
534     err = hwloc_topology_restrict (topology, restrictset, 0);
535     if (err) {
536       perror("Restricting the topology");
537       /* FALLTHRU */
538     }
539     hwloc_bitmap_free(restrictset);
540     free(restrictstring);
541   }
542 
543   if (mode == HWLOC_INFO_MODE_UNKNOWN) {
544     if (argc)
545       mode = HWLOC_INFO_MODE_OBJECTS;
546     else
547       mode = HWLOC_INFO_MODE_TOPOLOGY;
548   }
549 
550   if (mode == HWLOC_INFO_MODE_TOPOLOGY) {
551     hwloc_lstopo_show_summary(stdout, topology);
552 
553   } else if (mode == HWLOC_INFO_MODE_SUPPORT) {
554     const struct hwloc_topology_support *support = hwloc_topology_get_support(topology);
555 #define DO(x,y) printf(#x ":" #y " = %u\n", (unsigned char) support->x->y);
556     DO(discovery, pu);
557 
558     DO(cpubind, set_thisproc_cpubind);
559     DO(cpubind, get_thisproc_cpubind);
560     DO(cpubind, set_proc_cpubind);
561     DO(cpubind, get_proc_cpubind);
562     DO(cpubind, set_thisthread_cpubind);
563     DO(cpubind, get_thisthread_cpubind);
564     DO(cpubind, set_thread_cpubind);
565     DO(cpubind, get_thread_cpubind);
566     DO(cpubind, get_thisproc_last_cpu_location);
567     DO(cpubind, get_proc_last_cpu_location);
568     DO(cpubind, get_thisthread_last_cpu_location);
569 
570     DO(membind, set_thisproc_membind);
571     DO(membind, get_thisproc_membind);
572     DO(membind, set_proc_membind);
573     DO(membind, get_proc_membind);
574     DO(membind, set_thisthread_membind);
575     DO(membind, get_thisthread_membind);
576     DO(membind, set_area_membind);
577     DO(membind, get_area_membind);
578     DO(membind, alloc_membind);
579     DO(membind, firsttouch_membind);
580     DO(membind, bind_membind);
581     DO(membind, interleave_membind);
582     DO(membind, nexttouch_membind);
583     DO(membind, migrate_membind);
584     DO(membind, get_area_memlocation);
585 
586   } else if (mode == HWLOC_INFO_MODE_OBJECTS) {
587     struct hwloc_calc_location_context_s lcontext;
588     lcontext.topology = topology;
589     lcontext.topodepth = topodepth;
590     lcontext.only_hbm = -1;
591     lcontext.logical = logical;
592     lcontext.verbose = verbose_mode;
593     current_obj = 0;
594     while (argc >= 1) {
595       if (!strcmp(argv[0], "all") || !strcmp(argv[0], "root")) {
596 	hwloc_calc_process_location_info_cb(&lcontext, NULL, hwloc_get_root_obj(topology));
597       } else {
598 	/* try to match a type/depth followed by a special character */
599 	typelen = strspn(argv[0], "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
600 	if (typelen && (argv[0][typelen] == ':' || argv[0][typelen] == '=' || argv[0][typelen] == '[')) {
601 	  err = hwloc_calc_process_location(&lcontext, argv[0], typelen,
602 					    hwloc_calc_process_location_info_cb, NULL);
603 	}
604       }
605       argc--; argv++;
606     }
607 
608   } else assert(0);
609 
610   hwloc_topology_destroy (topology);
611 
612   return EXIT_SUCCESS;
613 }
614