Lister les méthodes documentées ou non, les variables
Philippe49
Membre
A la fois une réponse et une question
La réponse
Pour lister tous les symboles (y compris les méthodes documentées ou non documentées) présentes dans la librairie compilée et filtrer les lignes concernant une classe particulière, on peut exécuter sur le terminal :
nm /System/Library/Frameworks/AppKit.framework/AppKit | grep "TreeController"
La question
Ces méthodes non documentées sont utilisables pour débogguer provisoirement. mais est-il possible de les utiliser pour le code définitif d'une application ?
La réponse
Pour lister tous les symboles (y compris les méthodes documentées ou non documentées) présentes dans la librairie compilée et filtrer les lignes concernant une classe particulière, on peut exécuter sur le terminal :
nm /System/Library/Frameworks/AppKit.framework/AppKit | grep "TreeController"
La question
Ces méthodes non documentées sont utilisables pour débogguer provisoirement. mais est-il possible de les utiliser pour le code définitif d'une application ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
C'est bien sûr utilisable dans le code définitif d'une application utilisant cette version du Framework.
nm ne sort que les fonctions.
D'autre part, nm peut sortir toutes les fonctions d'un binaire, même celles (dans le cas d'une lib) qui ne sont pas "exportées" (appelables depuis un autre binaire) : elle sont donc inutilisables (c'est le cas des symboles dont le type -lettre dans la seconde colonne- est en minuscule).
L'utilisation de ce qu'on appelle undocumented (fais une recherche sur ce mot ici) est toujours risquée : dans le cas des méthodes Obj-C, il est aisé de vérifier leur existence (voire leur signature) afin de les appeler ou non.
Par contre, pour les fonctions, c'est plus complexe.
Or selon les versions du système, ces méthodes/fonctions peuvent être modifiées (disparaà®tre, ou changer de signature, ou faire autre chose que ce qu'elles faisaient avant).
.
Il y a deux manières d'utiliser une méthode non documentée : la surcharger ou l'appeler (dans ce cas on a un Warning car elle n'est bien sûr pas dans le .h)
Pour les fonctions, on peut juste les appeler, mais je ne vois pas comment certaines fonctions peuvent être inutilisables ???
Pour ça que j'ai dit "utilisant cette version du Framework" !Â
Exact.
Sauf si tu créés une décla de catégorie en haut du source utilisant la undocumented...
Inutilisables, car non "exportées".
Tu peux créer autant de fonctions que tu veux dans une lib, ce n'est pas pour autant que tu peux les appeler depuis une appli qui s'appuie sur cette lib, si ces fonctions ne sont pas exposées.
Prends l'exemple de la lib CoreGraphics.
Un nm de montre 2 symboles pouvant te donner l'impression de récupérer la valeur alpha d'une fenêtre :
[tt]904a3658 T _CGSGetWindowAlpha
9060b5e8 t _CGXGetWindowAlpha[/tt]
La 1ère est exportée : en effet tu peux l'utiliser dans tes applis :
La 2nde te plantera ton appli (surement sur un SIGABORT), puisque le symbole n'aura pas pu être résolu au chargement de la lib par ton appli.
D'ailleurs, la plupart des symboles non exposés (local en terminologie informatique) peuvent être purement et simplement supprimer de la table des symboles (qui est utilisée par nm) par la simple commande strip : tu ne les verras plus dans nm !
Oui, c'est pas faux...
Mais, framework est un peu trop restrictif.
OS X est composé de beaucoup de lib (statiques ou dynamiques), qui ne sont pas des frameworks.
C'est donc pourquoi, j'ai évoqué "la version du système" plus que "la version du framework".
.
Bonne idéeÂ
Qu'est-ce qui définit une fonction non "exportée" ?
Parce qu'il me semble qu'en faisant un Framework Cocoa, toutes les méthodes définies dans ce Framework sont accessibles, qu'elles-soient dans le .h ou non, je me trompe ? ???
Non, tu ne te trompes pas.
Mais tu restes trop focalisé sur "méthode".
Ce que montre nm (pour recoller au 1er post de Philippe49), c'est la table des symboles d'un binaire.
Le symbole peut être une implémentation d'une méthode Obj-C (donc, a priori toujours exportée, quoique...), mais aussi toute autre fonction du binaire (et les variables globales, les constantes, etc...).
Si, ces symboles (fonctions, variables globales, constantes, etc...) ne sont pas exportés, ils ne seront pas "linkable" par un autre binaire.
.
C'est les définitions "static" ? (ou je suis encore complètement à côté de la plaque ? )
Non.
static est un mot clé uniquement utilisé par les sources pour restreindre le "scope" d'un symbole lors du linkage final des .o .
Lis ce post pour plus de détail.
Stop !
Je ne crois pas avoir lu dans tes interventions quelque chose à côté de la plaque...
Sinon, je te garantis que certains d'entre nous te seraient "tombés sur le poil" (moi le premier) pour te remettre dans le droit chemin du cocoaà¯sme, religion d'état sur ce site.
.
Donc j'ai toujours pas compris comment on définit les fonctions "exportées" et les "non exportées" en codant une bibliothèque...
Pour reprendre ton exemple :
Est-ce dû à une différence de définition de CGSGetWindowAlpha et CGXGetWindowAlpha ?
J'imagine que les deux sont définies dans le .cpp puisqu'elles ne sont pas dans le .h
Mais comment précise-on qu'une est "utilisable" et l'autre non ?
On trouve class-dump ici
http://www.codethecode.com/Projects/class-dump/
Belle surprise  :o: il liste également les variables de la classe  :o
Un exemple d'utilisation ( -C choix de la classe, -r récursif )
class-dump -C NSNotification /System/Library/Frameworks/Cocoa.framework -r
:adios!: Avec une interface graphique !! :kicking:
class-dump permet les regex, la récursivité, ce qui semble plus difficile avec MagicHat .
Oui, mais tout cela me semble vrai également pour les méthodes documentées.
Le problème n'est-il pas plutôt la politique suivie par Apple : prévient-il lorsque les méthodes non documentées sont transformées lors de changements majeurs ?
Dans un autre monde parallèle, peut être.
Le propre d'une méthode non documentée, c'est qu'elle n'existe pas (du moins officiellement) !
Si Apple ne les documentent pas, le programmeur ne devrait pas l'utiliser.
Ce qui laisse tout loisir à la firme de Cupertino de modifier comme bon lui semble lesdites méthodes.
.
C'est justement parce que normalement ce sont des méthodes "privées" que tu n'es pas sensé utiliser.
C'est pour ça qu'elles n'apparaissent nulle part (dans la doc, j'entends), et qu'Apple se réserve le droit de les modifier sans prévenir, puisqu'officiellement tu ne devrais pas les connaà®tre ni les utiliser
Avez-vous vu un substitut ?
class-dump non plus d'ailleurs :
% class-dump -C NSNotification /System/Library/Frameworks/Cocoa.framework -r
class-dump: Fat archive (/usr/lib/libgcc_s.1.dylib) does not contain required cpu type: ppc7400.
/*
* Generated by class-dump 3.1.2.
*
* class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2007 by Steve Nygard.
*/
This file does not contain any Objective-C runtime information.
En revanche pour économiser les fichiers, le fichier Cocoa.h du framework fait importe les .h principaux des 3 autres frameworks. Mais avec class-dump on aurait du pouvoir voir la définition de toutes les classes de Cocoa...
Donc il contient bel et bien quelque, je dirais même qu'il contient tout, sauf les fichiers .h définis autre part.
Parce que class-dump fonctionne sous Leopard, mais à condition "d'attaquer" les frameworks individuels.
D'ailleurs, si on fait un class-dump sur le binaire de l'AppKit, on voit bien toutes les classes définies.
NB : j'ai fait le teste sur l'AppKit contenu dans les frameworks système, et j'ai utilisé directement le binaire et non pas le dossier.
À ce niveau du runtime, j'ai des doutes sur le fait qu'il y ait eu des changements majeurs !
D'après votre expérimentation, il s'agirait d'un dysfonctionnement du -r
[EDIT] je suis retourné sur le site, et il indique (Mac OS X 10.4+) et la mise à jour n'est sans doute pas faite.
Donc après peut-être qu'avant class-dump savait lire dans les "faux frameworks" comme Cocoa qui ne serait qu'un "wrapper", et que maintenant il ne sait plus... Mais déjà si tu lancais la commande class-dump sur les frameworks AppKit, CoreData et Fundation, tu pourrais voir si ça marche
Au contraire, il y en a eu beaucoup de modifications du runtime avec Leopard, pour le voir il te suffit de regarder dans le document Objective-C 2.0 Runtime Reference, dans la section Appendix A : Mac OS X 10.5 Delta.
Sur le runtime, oui, mais à ce niveau du runtime ??? (écriture des signatures dans le binaire)
Oui sur ces frameworks "sans récursion", cela fonctionne.
% class-dump -C NSNotification /System/Library/Frameworks/Foundation.framework
/*
* Â Â Generated by class-dump 3.1.2.
*
* Â Â class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2007 by Steve Nygard.
*/
/*
* File: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
* Arch: PowerPC 7400 (ppc7400)
* Â Â Â Current version: 677.1.0, Compatibility version: 300.0.0
*/
@interface NSNotificationCenter : NSObject
{
  void *_impl;
  void *_callback_block[4];
  void *_pad[8];
}
+ (id)defaultCenter;
+ (void)setNotificationCenterSerializeRemoves:(BOOL)fp8;
- (id)init;
...
%
Pas du tout ! Une méthode est une méthode.
Si certaines méthodes Objective-C possèdent une entrée dans la table de symbole de ton fichier Mach-O, c'est parce que gcc à fait une optimisation en transformant la méthode en fonction. Toutefois, si tu utilises les capacités objets et les capacités avancées de l'Objective-C sur les classes, alors gcc ne pourra plus transformer tes méthodes en "fonctions", et leur nom ne sera plus présents dans la table de symbole, mais uniquement dans la section "__module_info" qui contient, entre autres, la structure de classe, des propriétés, et des héritages.
Si si, du moment que le symbole est présent dans la table de symbole, ce qui est le cas des fonctions exportées comme non exportés par défaut (tant que tu n'a pas "stripé").
Seulement les fonctions système (notamment celle du linkeur dynamique dyld) te refuseront à priori d'y accéder. Mais du moment que tu as accès à la structure du header de l'image mach-o chargée en mémoire par le lieur dynamique (mach_header), tu peux très bien parser la table de symboles toi-même (nlist) et récupérer l'adresse de l'élément non exporté.
Pour ce qui est de l'exportation, en C :
- le mot clef "static" permet de forcer un symbole d'être global à un fichier objet (typiquement en .o). Par la même occasion, il permet de dire au compilateur que ce symbole n'est pas exporté (ce qui, donc, ne l'empêchera pas d'être dans la table de symboles).
- le mot clef "export" permet de forcer un symbole d'être exporté. Ce mot clef est implicitement mis devant les déclarations de fonction, ce qui fait que quand on déclare le prototype de fonction dans un fichier .h, quand gcc tente de compiler le fichier, il ne tente pas de trouver le symbole dans l'objet local : il le laisse en attente de résolution pour le linkage.
Oui, c'est plus une modification de la hiérarchie et du contenus des frameworks, du fait de l'évolution du frameworks et du langage.
Mais ni Mach-O, ni Fat n'ont changés eux. D'ailleurs je ne pense pas qu'ils changent avant très longtemps. La souplesse du Mach-O permet de garder ce format tel quel pour encore longtemps.